From 1c97c38c1b3851f3fb3138f7ec67940df694a7e7 Mon Sep 17 00:00:00 2001 From: Nick Baur <79518844+baurnick@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:01:40 +0200 Subject: [PATCH] DEAR-129: add styling to dashbaord and remove unused components --- app/(auth)/login/page.tsx | 23 ++- app/(main)/(home)/components/AlertWidget.tsx | 12 +- .../(home)/components/EmotionSurvey.tsx | 46 +++--- .../(home)/components/HappinessSurvey.tsx | 78 ++++----- .../(home)/components/InactivityAlert.tsx | 48 ------ app/(main)/(home)/components/SprintWidget.tsx | 52 ++++-- .../(home)/components/SurveyHoverCard.tsx | 33 ++++ app/(main)/(home)/components/Widget.tsx | 6 +- app/(main)/(home)/components/WidgetRow.tsx | 63 ------- .../(home)/components/WorkKindSurvey.tsx | 111 ------------- .../(home)/components/WorktypeSurvey.tsx | 89 ++++++++++ app/(main)/(home)/components/index.ts | 6 + app/(main)/(home)/page.tsx | 61 ++----- .../onboarding/components/SelectableCard.tsx | 2 +- components/Buttons/SurveyHappinessButton.tsx | 18 -- components/Cards/Widget.tsx | 30 ---- components/ui/Buttons/Button.tsx | 5 +- package-lock.json | 155 +++++++++++------- package.json | 1 + tailwind.config.ts | 4 + 20 files changed, 362 insertions(+), 481 deletions(-) delete mode 100644 app/(main)/(home)/components/InactivityAlert.tsx create mode 100644 app/(main)/(home)/components/SurveyHoverCard.tsx delete mode 100644 app/(main)/(home)/components/WidgetRow.tsx delete mode 100644 app/(main)/(home)/components/WorkKindSurvey.tsx create mode 100644 app/(main)/(home)/components/WorktypeSurvey.tsx create mode 100644 app/(main)/(home)/components/index.ts delete mode 100644 components/Buttons/SurveyHappinessButton.tsx delete mode 100644 components/Cards/Widget.tsx diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index 3a9dd3f..80400c7 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -1,6 +1,7 @@ 'use client'; import * as React from 'react'; +import { motion } from 'framer-motion'; import Logo from '@components/ui/Logo/Logo'; import UserAuthForm from './components/UserAuthForm'; @@ -9,12 +10,22 @@ const LoginPage: React.FC = () => (
-

Where productivity meets happiness

-

- Discover a new way to track your happiness and boost your productivity. yappi helps you monitor your emotional - well-being, learn from your experiences, and achieve greater efficiency in your daily life. Join us now and - take the first step towards a happier, more productive you. -

+ +

Where productivity meets happiness

+

+ Discover a new way to track your happiness and boost your productivity. yappi helps you monitor your + emotional well-being, learn from your experiences, and achieve greater efficiency in your daily life. Join + us now and take the first step towards a happier, more productive you. +

+
diff --git a/app/(main)/(home)/components/AlertWidget.tsx b/app/(main)/(home)/components/AlertWidget.tsx index be2ba51..2f6d9d8 100644 --- a/app/(main)/(home)/components/AlertWidget.tsx +++ b/app/(main)/(home)/components/AlertWidget.tsx @@ -1,21 +1,21 @@ import * as React from 'react'; import { Card, CardContent, CardHeader } from '@components/ui/Card/Card'; +import { Siren } from 'lucide-react'; interface AlertWidgetProps { - icon: React.ReactNode; days: number; } -const AlertWidget: React.FC = ({ icon, days }) => ( - +const AlertWidget: React.FC = ({ days }) => ( +
-
- {icon} +
+
-
+

{days}

Days without any happiness tracking.

diff --git a/app/(main)/(home)/components/EmotionSurvey.tsx b/app/(main)/(home)/components/EmotionSurvey.tsx index 67f7da5..1a9a383 100644 --- a/app/(main)/(home)/components/EmotionSurvey.tsx +++ b/app/(main)/(home)/components/EmotionSurvey.tsx @@ -1,12 +1,13 @@ 'use client'; import * as React from 'react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@components/ui/Card/Card'; +import { Card, CardContent, CardHeader } from '@components/ui/Card/Card'; import { User } from '@/types/UserType'; import { Emotion } from '@/types/EmotionType'; -import { Badge } from '@components/ui/Badge/Badge'; import { toast } from '@components/ui/Toast/use-toast'; import useDashboardClient from '@hooks/useDashboardClient'; +import { Button } from '@components/ui/Buttons/Button'; +import SurveyHoverCard from './SurveyHoverCard'; interface EmotionSurveyProps { emotions: Array; @@ -36,29 +37,26 @@ const EmotionSurvey: React.FC = ({ fetchDashboardData, emoti }; return ( - - - Survey - How do you feel? - - We value your well-being and would love to know how you feel today. Please select the emotion that best - represents your current mood. Your feedback helps us understand your overall happiness and track changes over - time. - + + +
+ - - -
- {emotions.map((emotion) => ( - handleClick(emotion.id)} - className="cursor-pointer p-4 text-sm transition-colors duration-200 ease-in-out hover:bg-primaryBlue-main" - > - {emotion.name} - - ))} + +
+
+ {emotions.map((emotion) => ( + + ))} +
+

How do you feel?

diff --git a/app/(main)/(home)/components/HappinessSurvey.tsx b/app/(main)/(home)/components/HappinessSurvey.tsx index 21ae722..1038d06 100644 --- a/app/(main)/(home)/components/HappinessSurvey.tsx +++ b/app/(main)/(home)/components/HappinessSurvey.tsx @@ -1,13 +1,14 @@ 'use client'; import * as React from 'react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@components/ui/Card/Card'; -import { Annoyed, Frown, Laugh, Smile } from 'lucide-react'; -import SurveyHappinessButton from '@components/Buttons/SurveyHappinessButton'; +import { User } from '@/types/UserType'; +import { Card, CardContent, CardHeader } from '@components/ui/Card/Card'; +import useDashboardClient from '@hooks/useDashboardClient'; import { SubmitHappinessScoreDTO } from '@/types/SurveyType'; +import { Annoyed, Frown, Laugh, Smile } from 'lucide-react'; +import { Button } from '@components/ui/Buttons/Button'; import { toast } from '@components/ui/Toast/use-toast'; -import useDashboardClient from '@hooks/useDashboardClient'; -import { User } from '@/types/UserType'; +import SurveyHoverCard from './SurveyHoverCard'; interface HappinessSurveyProps { fetchDashboardData: () => void; @@ -15,11 +16,8 @@ interface HappinessSurveyProps { } const HappinessSurvey: React.FC = ({ fetchDashboardData, user }) => { - const [rotateButton, setRotateButton] = React.useState(null); const { submitHappinessScore } = useDashboardClient(); - const iconClasses = (score: number) => `h-12 w-12 ${rotateButton === score ? 'rotate-360' : ''}`; - const handleHappinessSubmit = async (score: number) => { const happinessScore: SubmitHappinessScoreDTO = { score, @@ -44,51 +42,35 @@ const HappinessSurvey: React.FC = ({ fetchDashboardData, u }; const handleClick = (score: number) => { - setRotateButton(score); - setTimeout(() => setRotateButton(null), 1000); handleHappinessSubmit(score); }; return ( - - - Survey - How happy are you with your working day? - - We want to know how satisfied you are with your workday today. Your feedback is important to us and helps us - understand your daily work experience. - + + +
+ - -
- } - /> - } - /> - } - /> - } - /> + +
+
+ + + + +
+

How happy are you with your working day?

diff --git a/app/(main)/(home)/components/InactivityAlert.tsx b/app/(main)/(home)/components/InactivityAlert.tsx deleted file mode 100644 index deff3a4..0000000 --- a/app/(main)/(home)/components/InactivityAlert.tsx +++ /dev/null @@ -1,48 +0,0 @@ -'use client'; - -import * as React from 'react'; - -import { DashboardDTO } from '@/types/DashboardType'; -import Widget from '@components/Cards/Widget'; -import { Activity, Annoyed, Bike, CircleSlash2, Component, Megaphone, Siren } from 'lucide-react'; -import AlertWidget from './AlertWidget'; -import Widget2 from './Widget'; -import SprintWidget from './SprintWidget'; - -interface DashboardOverviewProps { - dashboardData?: DashboardDTO; -} - -const InactivityAlert: React.FC = ({ dashboardData }) => ( -
- } days={12} /> -
-
- } content="Coding" description="Most tracked worktype" /> -
- } - content={} - description="Average Happiness" - /> - } content="Bored, Lonely" description="Most tracked emotions" /> - } content="4" description="Days left in the sprint" /> - } content="Coding" description="Most tracked worktype" /> -
- } days={12} /> - , - }} - content={{ - mainContent: 'No Happiness tracking since 52 days.', - subContent: dashboardData?.averageScore, - }} - borderColor="border-primaryBlue-main" - fontColor="text-primaryBlue-main" - /> -
-); - -export default InactivityAlert; diff --git a/app/(main)/(home)/components/SprintWidget.tsx b/app/(main)/(home)/components/SprintWidget.tsx index 6a187cf..21c64c8 100644 --- a/app/(main)/(home)/components/SprintWidget.tsx +++ b/app/(main)/(home)/components/SprintWidget.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { Card, CardContent, CardHeader } from '@components/ui/Card/Card'; +import { motion, useAnimation } from 'framer-motion'; interface SprintWidgetProps { icon: React.ReactNode; @@ -7,21 +8,40 @@ interface SprintWidgetProps { description: string; } -const SprintWidget: React.FC = ({ icon, content, description }) => ( - - -
-
- {icon} -
- - -
-

{content}

-

{description}

-
-
- -); +const SprintWidget: React.FC = ({ icon, content, description }) => { + const controls = useAnimation(); + + const handleHoverStart = () => { + controls.start({ + x: [-30, 30], + }); + }; + + const handleHoverEnd = () => { + controls.stop(); + controls.set({ x: 0 }); + }; + + return ( + + + +
+
+ + {icon} + +
+ + +
+

{content}

+

{description}

+
+
+ + + ); +}; export default SprintWidget; diff --git a/app/(main)/(home)/components/SurveyHoverCard.tsx b/app/(main)/(home)/components/SurveyHoverCard.tsx new file mode 100644 index 0000000..798f357 --- /dev/null +++ b/app/(main)/(home)/components/SurveyHoverCard.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { HoverCard, HoverCardTrigger, HoverCardContent } from '@components/ui/HoverCard/HoverCard'; +import { FilePlus } from 'lucide-react'; + +interface SurveyHoverCardProps { + title: string; + description: string; +} + +const SurveyHoverCard: React.FC = ({ title, description }) => ( + + +
+ +
+
+ +
+
+ +
+
+
+

{title}

+

{description}

+
+
+
+
+
+); + +export default SurveyHoverCard; diff --git a/app/(main)/(home)/components/Widget.tsx b/app/(main)/(home)/components/Widget.tsx index 027706e..0ece139 100644 --- a/app/(main)/(home)/components/Widget.tsx +++ b/app/(main)/(home)/components/Widget.tsx @@ -7,7 +7,7 @@ interface WidgetProps { description: string; } -const Widget2: React.FC = ({ icon, content, description }) => ( +const Widget: React.FC = ({ icon, content, description }) => (
@@ -17,11 +17,11 @@ const Widget2: React.FC = ({ icon, content, description }) => (
-

{content}

+

{content}

{description}

); -export default Widget2; +export default Widget; diff --git a/app/(main)/(home)/components/WidgetRow.tsx b/app/(main)/(home)/components/WidgetRow.tsx deleted file mode 100644 index 67c5a24..0000000 --- a/app/(main)/(home)/components/WidgetRow.tsx +++ /dev/null @@ -1,63 +0,0 @@ -'use client'; - -import * as React from 'react'; - -import { DashboardDTO } from '@/types/DashboardType'; -import Widget from '@components/Cards/Widget'; -import { AudioWaveform, Bike, CircleSlash } from 'lucide-react'; -import Progress from '@components/ui/Progress/Progress'; -import AverageHappinessButton from '@components/Buttons/AverageHappinessButton'; - -interface DashboardOverviewProps { - dashboardData?: DashboardDTO; -} - -const WidgetRow: React.FC = ({ dashboardData }) => ( -
- , - }} - content={{ - mainContent: , - }} - /> - , - }} - content={{ - mainContent: , - subContent: '4 days left', - }} - /> - , - }} - content={{ - mainContent:
Bored, Lonely, Sick
, - }} - /> - - {dashboardData.mostVotedWorkKind.workKindName} - -
- ) : ( - '-' - ), - }} - /> -
-); - -export default WidgetRow; diff --git a/app/(main)/(home)/components/WorkKindSurvey.tsx b/app/(main)/(home)/components/WorkKindSurvey.tsx deleted file mode 100644 index 62c7e02..0000000 --- a/app/(main)/(home)/components/WorkKindSurvey.tsx +++ /dev/null @@ -1,111 +0,0 @@ -'use client'; - -import * as React from 'react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@components/ui/Card/Card'; -import { toast } from '@components/ui/Toast/use-toast'; -import { WorkKind } from '@/types/WorkKindType'; -import { Annoyed, Frown, Laugh, Smile } from 'lucide-react'; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@components/ui/Table/BasicTable'; -import useDashboardClient from '@hooks/useDashboardClient'; -import { SubmitWorkKindScoreDTO } from '@/types/SurveyType'; -import { User } from '@/types/UserType'; -import SurveyHappinessButton from '@components/Buttons/SurveyHappinessButton'; - -interface WorkKindSurveyProps { - workKinds: Array; - user: User; - fetchDashboardData: () => void; -} - -const WorkKindSurvey: React.FC = ({ fetchDashboardData, workKinds, user }) => { - const { submitWorkKindScore } = useDashboardClient(); - - const handleClick = async (score: number, workKindId: number) => { - const workKindScore: SubmitWorkKindScoreDTO = { - score, - userId: user.id, - workKindId, - }; - - try { - await submitWorkKindScore(workKindScore); - toast({ - title: 'Success!', - description: `Happiness score submitted`, - }); - fetchDashboardData(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (error: any) { - toast({ - title: 'Error!', - description: `Failed to submit score: ${error.message}`, - variant: 'destructive', - }); - } - }; - - return ( - - - Survey - How happy are you with specific worktypes? - - We want to understand your satisfaction with the different types of work you do. Your feedback helps us - improve and tailor tasks to better fit your preferences. - - - - - - - - Work type - Happiness - - - - {workKinds.map((workKind) => ( - - {workKind.name} - -
- handleClick(score, workKind.id)} - className="bg-tertiaryBG-light" - icon={} - /> - handleClick(score, workKind.id)} - className="bg-primaryRed-light text-primaryRed-main" - icon={} - /> - handleClick(score, workKind.id)} - className="bg-primaryBlue-light text-primaryBlue-main" - icon={} - /> - handleClick(score, workKind.id)} - className="bg-primaryGreen-light text-primaryGreen-main" - icon={} - /> -
-
-
- ))} -
-
-
-
- ); -}; - -export default WorkKindSurvey; diff --git a/app/(main)/(home)/components/WorktypeSurvey.tsx b/app/(main)/(home)/components/WorktypeSurvey.tsx new file mode 100644 index 0000000..941d55f --- /dev/null +++ b/app/(main)/(home)/components/WorktypeSurvey.tsx @@ -0,0 +1,89 @@ +'use client'; + +import * as React from 'react'; +import { Card, CardContent, CardHeader } from '@components/ui/Card/Card'; +import { WorkKind } from '@/types/WorkKindType'; +import { Annoyed, Frown, Laugh, Smile } from 'lucide-react'; +import useDashboardClient from '@hooks/useDashboardClient'; +import { User } from '@/types/UserType'; +import { SubmitWorkKindScoreDTO } from '@/types/SurveyType'; +import { Button } from '@components/ui/Buttons/Button'; +import { toast } from '@components/ui/Toast/use-toast'; +import SurveyHoverCard from './SurveyHoverCard'; + +interface WorktypeSurveyProps { + workKinds: Array; + user: User; + fetchDashboardData: () => void; +} + +const WorktypeSurvey: React.FC = ({ fetchDashboardData, workKinds, user }) => { + const { submitWorkKindScore } = useDashboardClient(); + + const handleClick = async (score: number, workKindId: number) => { + const workKindScore: SubmitWorkKindScoreDTO = { + score, + userId: user.id, + workKindId, + }; + + try { + await submitWorkKindScore(workKindScore); + toast({ + title: 'Success!', + description: `Happiness score submitted`, + }); + fetchDashboardData(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + toast({ + title: 'Error!', + description: `Failed to submit score: ${error.message}`, + variant: 'destructive', + }); + } + }; + + return ( + + +
+ + + + {workKinds.map((workKind) => ( +
+

{workKind.name}

+
+ + + + +
+
+ ))} +

How happy are you with specific worktypes?

+
+ + ); +}; + +export default WorktypeSurvey; diff --git a/app/(main)/(home)/components/index.ts b/app/(main)/(home)/components/index.ts new file mode 100644 index 0000000..55ae29a --- /dev/null +++ b/app/(main)/(home)/components/index.ts @@ -0,0 +1,6 @@ +export { default as HappinessSurvey } from './HappinessSurvey'; +export { default as WorktypeSurvey } from './WorktypeSurvey'; +export { default as EmotionSurvey } from './EmotionSurvey'; +export { default as Widget } from './Widget'; +export { default as AlertWidget } from './AlertWidget'; +export { default as SprintWidget } from './SprintWidget'; diff --git a/app/(main)/(home)/page.tsx b/app/(main)/(home)/page.tsx index d740328..94c62e3 100644 --- a/app/(main)/(home)/page.tsx +++ b/app/(main)/(home)/page.tsx @@ -5,22 +5,15 @@ import { useRouter } from 'next/navigation'; import Loading from '@components/Loading/Loading'; import Error from '@components/Error/Error'; import { useAuth } from '@providers/AuthProvider'; -import { ShipWheel } from 'lucide-react'; -import HappinessSurvey from '@/(main)/(home)/components/HappinessSurvey'; -import Widget from '@components/Cards/Widget'; +import { Activity, Bike, Component, CircleSlash2, Annoyed } from 'lucide-react'; import useDashboardClient from '@hooks/useDashboardClient'; import { toast } from '@components/ui/Toast/use-toast'; import { WorkKind } from '@/types/WorkKindType'; import useWorkKindClient from '@hooks/useWorkKindClient'; -import WorkKindSurvey from '@/(main)/(home)/components/WorkKindSurvey'; import { DashboardDTO } from '@/types/DashboardType'; import useEmotionClient from '@hooks/useEmotionClient'; import { Emotion } from '@/types/EmotionType'; -import EmotionSurvey from '@/(main)/(home)/components/EmotionSurvey'; -import WidgetRow from '@/(main)/(home)/components/WidgetRow'; -import InactivityAlert from '@/(main)/(home)/components/InactivityAlert'; -import FeedbackSurvey from '@/(main)/(home)/components/FeedbackSurvey'; -import AverageHappinessButton from '@components/Buttons/AverageHappinessButton'; +import { HappinessSurvey, WorktypeSurvey, EmotionSurvey, Widget, AlertWidget, SprintWidget } from './components'; const Home: React.FC = () => { const { user, isLoading, error } = useAuth(); @@ -28,7 +21,7 @@ const Home: React.FC = () => { const { getDashboardData } = useDashboardClient(); const { getWorkKinds } = useWorkKindClient(); const { getEmotions } = useEmotionClient(); - const [dashboardData, setDashboardData] = React.useState(); + const [setDashboardData] = React.useState(); const [workKinds, setWorkKinds] = React.useState([]); const [emotions, setEmotions] = React.useState([]); const [isLoadingWorkKinds, setIsLoadingWorkKinds] = React.useState(); @@ -100,42 +93,18 @@ const Home: React.FC = () => {
{user && user.hasTeam ? (
-
- - -
- -
-
- - - -
-
- -
- , - }} - content={{ - mainContent: 53, - subContent: 'Story Points', - }} - /> - , - }} - content={{ - mainContent: , - }} - /> -
-
-
+ + + + + } content="4" description="Days left in the sprint" /> + } content="Bored, Lonely" description="Most tracked emotions" /> + } content="Coding" description="Most tracked worktype" /> + } + content={} + description="Average Happiness" + />
) : ( diff --git a/app/(onboarding)/onboarding/components/SelectableCard.tsx b/app/(onboarding)/onboarding/components/SelectableCard.tsx index f2a903e..b28d5ad 100644 --- a/app/(onboarding)/onboarding/components/SelectableCard.tsx +++ b/app/(onboarding)/onboarding/components/SelectableCard.tsx @@ -12,7 +12,7 @@ interface SelectableCardProps { const SelectableCard: React.FC = ({ onClick, title, description, icon }) => ( diff --git a/components/Buttons/SurveyHappinessButton.tsx b/components/Buttons/SurveyHappinessButton.tsx deleted file mode 100644 index 5ea9d52..0000000 --- a/components/Buttons/SurveyHappinessButton.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { Button } from '@components/ui/Buttons/Button'; - -interface SurveyButtonProps { - score: number; - onClick: (score: number) => void; - className: string; - icon: React.ReactNode; - size: 'icon' | 'default' | 'mood' | 'sm' | 'lg' | 'navigation' | null | undefined; -} - -const SurveyHappinessButton: React.FC = ({ score, onClick, className, icon, size }) => ( - -); - -export default SurveyHappinessButton; diff --git a/components/Cards/Widget.tsx b/components/Cards/Widget.tsx deleted file mode 100644 index 9437773..0000000 --- a/components/Cards/Widget.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import { Card, CardHeader, CardTitle, CardContent } from '@components/ui/Card/Card'; - -interface CardProps { - header: { - title: string; - icon?: React.ReactNode; - }; - content: { - mainContent: React.ReactNode; - subContent?: React.ReactNode; - }; - borderColor?: string; - fontColor?: string; -} - -const Widget: React.FC = ({ header, content, borderColor, fontColor }) => ( - - - {header.title} - {header.icon &&
{header.icon}
} -
- -
{content.mainContent}
- {content.subContent &&

{content.subContent}

} -
-
-); - -export default Widget; diff --git a/components/ui/Buttons/Button.tsx b/components/ui/Buttons/Button.tsx index 00c70f3..395b19b 100644 --- a/components/ui/Buttons/Button.tsx +++ b/components/ui/Buttons/Button.tsx @@ -20,15 +20,16 @@ const buttonVariants = cva( link: 'text-slate-900 underline-offset-4 hover:underline dark:text-slate-50', selected: 'bg-tertiaryBG-light dark:bg-secondaryBG-dark', icon: 'dark:hover:bg-secondaryBG-dark hover:bg-tertiaryBG-light', - mood: 'rounded-2xl hover:bg-secondaryBG-light focus-visible:bg-secondaryBG-light', + mood: 'rounded-3xl bg-tertiaryBG-light hover:bg-slate-50 text-black hover:text-black p-4', }, size: { default: 'h-10 px-4 py-2', sm: ' rounded-md px-3', lg: 'h-11 rounded-md px-8', icon: 'h-8 w-8', + survey: 'h-12 w-12', navigation: 'h-10 w-10', - mood: 'h-20 w-20', + mood: 'h-28 w-28', }, }, defaultVariants: { diff --git a/package-lock.json b/package-lock.json index 1a03963..4fede56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "framer-motion": "^11.3.17", "input-otp": "^1.2.4", "lucide-react": "^0.395.0", "next": "14.2.3", @@ -125,9 +126,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1515,9 +1516,9 @@ "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", "dev": true }, "node_modules/@swc/counter": { @@ -1913,12 +1914,15 @@ } }, "node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2384,15 +2388,15 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2745,9 +2749,9 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2926,6 +2930,18 @@ "node": ">=10.13.0" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -4049,6 +4065,30 @@ "node": ">= 6" } }, + "node_modules/framer-motion": { + "version": "11.3.19", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.19.tgz", + "integrity": "sha512-+luuQdx4AsamyMcvzW7jUAJYIKvQs1KE7oHvKkW3eNzmo0S+3PSDWjBuQkuIP9WyneGnKGMLUSuHs8OP7jKpQg==", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4379,9 +4419,9 @@ } }, "node_modules/husky": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.1.tgz", - "integrity": "sha512-fCqlqLXcBnXa/TJXmT93/A36tJsjdJkibQ1MuIiFyCCYUlpYpIaj2mv1w+3KR6Rzu1IC3slFTje5f6DUp2A2rg==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.3.tgz", + "integrity": "sha512-ET3TQmQgdIu0pt+jKkpo5oGyg/4MQZpG6xcam5J5JyNJV+CBT23OBpCF15bKHKycRyMH9k6ONy8g2HdGIsSkMQ==", "dev": true, "bin": { "husky": "bin.js" @@ -5301,14 +5341,14 @@ "dev": true }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -5510,6 +5550,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -6239,9 +6291,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "funding": [ { "type": "opencollective", @@ -6870,51 +6922,36 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -7579,9 +7616,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", diff --git a/package.json b/package.json index 0ec1769..de43765 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "framer-motion": "^11.3.17", "input-otp": "^1.2.4", "lucide-react": "^0.395.0", "next": "14.2.3", diff --git a/tailwind.config.ts b/tailwind.config.ts index e34421e..901001f 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -40,6 +40,10 @@ const config: Config = { main: 'rgba(78, 138, 227)', light: 'rgba(78, 138, 227, 0.2)', }, + primaryYellow: { + main: 'rgba(255, 179, 0)', + light: 'rgba(255, 179, 0, 0.2)', + }, // background colors primaryBG: {