Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@
"preview": "vite preview"
},
"dependencies": {
"classnames": "^2.3.2",
"framer-motion": "^10.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.7",
"typescript": "^4.9.3",
"vite": "^4.1.0"
}
}
}
6 changes: 6 additions & 0 deletions postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
42 changes: 0 additions & 42 deletions src/App.css

This file was deleted.

34 changes: 0 additions & 34 deletions src/App.tsx

This file was deleted.

3 changes: 3 additions & 0 deletions src/assets/css/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
1 change: 0 additions & 1 deletion src/assets/react.svg

This file was deleted.

9 changes: 9 additions & 0 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { FC, PropsWithChildren } from "react";

export const Card: FC<PropsWithChildren> = ({ children }) => {
return (
<div className="bg-custom-purple-600 rounded-2xl shadow-card">
<div>{children}</div>
</div>
);
};
55 changes: 55 additions & 0 deletions src/components/CircleProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { motion } from "framer-motion";

interface ICircleProgressProps {
size: number;
color: string;
percentage: number;
}

export const CircleProgress: React.FC<ICircleProgressProps> = ({
size,
color,
percentage,
}) => {
const strokeWidth = size / 7;
const radius = size / 2 - strokeWidth / 2;

return (
<svg
className={`w-20 h-20 md:w-40 md:h-40`}
viewBox={`0 0 ${size} ${size}`}
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{ transform: "rotate(270deg)" }}
>
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
strokeWidth={strokeWidth}
className="stroke-custom-purple-700"
/>

<motion.circle
className={color}
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
strokeWidth={strokeWidth}
pathLength={100}
strokeLinecap="round"
strokeDasharray={100}
initial={{ strokeDashoffset: 100 }}
animate={{ strokeDashoffset: 100 - percentage }}
transition={{
delay: 0,
type: "tween",
duration: (percentage / 100) * 2,
ease: "easeOut",
}}
/>
</svg>
);
};
31 changes: 31 additions & 0 deletions src/components/Icons/IconHappyPerson.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
interface IconHappyPersonProps extends React.ComponentPropsWithoutRef<"svg"> {}

export const IconHappyPerson = (props: IconHappyPersonProps) => (
<svg
width={54}
height={55}
viewBox="0 0 54 55"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<circle cx={27} cy={27.5} r={27} fill="url(#paint0_linear_201_65)" />
<path
d="M12.656 31.297c-.932 0-1.696.757-1.6 1.684a16.453 16.453 0 0032.733 0c.095-.927-.67-1.684-1.602-1.684H12.657zM23.498 21.172c.536 0 .98-.438.885-.966a5.484 5.484 0 00-10.797 0c-.095.528.349.966.885.966s.957-.443 1.102-.959a3.544 3.544 0 016.822 0c.145.516.567.959 1.103.959zM39.53 21.172c.535 0 .979-.438.884-.966a5.484 5.484 0 00-10.797 0c-.095.528.349.966.885.966s.958-.443 1.103-.959a3.544 3.544 0 016.822 0c.145.516.566.959 1.102.959z"
fill="#363447"
/>
<defs>
<linearGradient
id="paint0_linear_201_65"
x1={27}
y1={0.5}
x2={27}
y2={54.5}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#81FBB8" />
<stop offset={1} stopColor="#28C76F" />
</linearGradient>
</defs>
</svg>
);
9 changes: 9 additions & 0 deletions src/components/Sales/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Card } from "../Card";

export const Sales: React.FC = () => {
return (
<Card>
<span className="text-white">Vendas por dia da semana</span>
</Card>
);
};
22 changes: 22 additions & 0 deletions src/components/Score.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FC } from "react";
import { Card } from "./Card";
import { IconHappyPerson } from "./Icons/IconHappyPerson";

export const Score: FC = () => {
return (
<Card>
<div className="flex flex-col h-72 justify-between items-center p-7">
<span className="font-inter font-semibold text-2xl text-white">
NPS Geral
</span>
<span className="font-inter font-semibold text-2xl text-custom-green-500 flex flex-col justify-center items-center gap-2">
<IconHappyPerson />
Excelente!
</span>
<span className="font-inter font-normal text-sm text-white">
NPS Score 75
</span>
</div>
</Card>
);
};
24 changes: 24 additions & 0 deletions src/components/Statistics/components/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import classNames from "classnames";
import { FC, useMemo } from "react";
import { formatterNumbers } from "../../../utils/formatterNumbers";

interface IItemProps {
title: string;
value: number;
color: string;
}

export const ItemStatistics: FC<IItemProps> = ({ title, value, color }) => {
const valueFormatted = useMemo(() => {
return formatterNumbers(value, 1);
}, [value]);

return (
<div className="flex gap-1 text-white font-inter text-sm font-medium">
<div className={classNames("h-4 w-4 rounded-full", color)}></div>
<div>
{title} {valueFormatted}
</div>
</div>
);
};
66 changes: 66 additions & 0 deletions src/components/Statistics/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { FC, useMemo } from "react";
import { Card } from "../Card";
import { CircleProgress } from "../CircleProgress";
import { ItemStatistics } from "./components/Item";

interface IStatisticsProps {
title: string;
expected: number;
reached: number;
backgroundColor: string;
strokeColor: string;
}

export const Statistics: FC<IStatisticsProps> = ({
title,
expected,
reached,
backgroundColor,
strokeColor,
}) => {
const percentage = useMemo(() => {
const value = (reached / expected) * 100;

if (value > 100) return 100;

return Math.ceil(value);
}, [reached, expected]);

return (
<Card>
<div className="py-7 md:px-12">
<div className="flex flex-col items-center justify-between gap-4">
<span className="font-inter font-semibold text-2xl text-white">
{title}
</span>
<div className="relative">
<CircleProgress
size={8}
color={strokeColor}
percentage={percentage}
/>

<div className="absolute inset-0 h-full w-full rounded-full items-center justify-center flex flex-col text-white">
<span className="font-inter text-sm md:text-3xl font-bold">
{percentage}%
</span>
<span className="font-inter text-base font-light">alcançada</span>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<ItemStatistics
title="Esperado"
value={expected}
color={"bg-custom-purple-700"}
/>
<ItemStatistics
title="Alcançado"
value={reached}
color={backgroundColor}
/>
</div>
</div>
</div>
</Card>
);
};
Loading