-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #46 from wordigo/fix/dashboard
feat: new dashboard
- Loading branch information
Showing
12 changed files
with
14,814 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
apps/next/src/components/Layout/Dashboard/DashboardHeader/Feedback/Feedback.constants.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { useTranslation } from "next-i18next"; | ||
|
||
export interface IFeedbackType { | ||
title: string; | ||
imageSrc: string; | ||
level: number; | ||
} | ||
|
||
const useFeedbacks = (): IFeedbackType[] => { | ||
const { t } = useTranslation(); | ||
|
||
return [ | ||
{ | ||
title: t("general.too_bad"), | ||
imageSrc: "/images/faces/very_bad.svg", | ||
level: 1, | ||
}, | ||
{ | ||
title: t("general.bad"), | ||
imageSrc: "/images/faces/very_bad.svg", | ||
level: 2, | ||
}, | ||
{ | ||
title: t("general.not_bad"), | ||
imageSrc: "/images/faces/not_bad.svg", | ||
level: 3, | ||
}, | ||
{ | ||
title: t("general.good"), | ||
imageSrc: "/images/faces/good.svg", | ||
level: 4, | ||
}, | ||
{ | ||
title: t("general.very_good"), | ||
imageSrc: "/images/faces/very_good.svg", | ||
level: 5, | ||
}, | ||
]; | ||
}; | ||
|
||
export default useFeedbacks; |
126 changes: 126 additions & 0 deletions
126
apps/next/src/components/Layout/Dashboard/DashboardHeader/Feedback/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import useFeedbacksConstants, { | ||
type IFeedbackType, | ||
} from "./Feedback.constants"; | ||
import CButton from "@/components/UI/Button"; | ||
import { usePostFeedBackMutation } from "@/store/feedback/api"; | ||
import { | ||
Button, | ||
Popover, | ||
PopoverContent, | ||
PopoverTrigger, | ||
Textarea, | ||
Tooltip, | ||
TooltipContent, | ||
TooltipProvider, | ||
TooltipTrigger, | ||
toast, | ||
} from "@wordigo/ui"; | ||
import { cn } from "@wordigo/ui/lib/utils"; | ||
import { useTranslation } from "next-i18next"; | ||
import Image from "next/image"; | ||
import { useState } from "react"; | ||
|
||
const Feedback = () => { | ||
const { t } = useTranslation(); | ||
const [active, setActive] = useState(); | ||
const feedbacks = useFeedbacksConstants(); | ||
const [inputValue, setInputValue] = useState<string>(""); | ||
const [isFeedbackShow, setFeedbackShow] = useState(false); | ||
const [FeedBack, { isLoading }] = usePostFeedBackMutation(); | ||
|
||
const handleSubmitFeedback = () => { | ||
void FeedBack({ | ||
description: inputValue, | ||
rate: active, | ||
}) | ||
.then(() => { | ||
toast({ | ||
title: t("notifications.success"), | ||
description: t("feedback.success"), | ||
}); | ||
setFeedbackShow(false); | ||
}) | ||
.catch(() => { | ||
toast({ | ||
title: t("notifications.error"), | ||
description: t("feedback.error"), | ||
}); | ||
}); | ||
}; | ||
|
||
return ( | ||
<Popover open={isFeedbackShow} onOpenChange={setFeedbackShow}> | ||
<PopoverTrigger asChild> | ||
<Button variant="outline">{t("feedback.title")}</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className="w-80"> | ||
<div className="grid gap-4"> | ||
<div className="grid gap-2"> | ||
<div className="flex flex-col items-center gap-4"> | ||
<Textarea | ||
id="width" | ||
placeholder={t("feedback.placeholder")} | ||
className="col-span-2 h-8" | ||
onChange={(e) => setInputValue(e.target.value)} | ||
/> | ||
</div> | ||
</div> | ||
<div className="flex gap-x-2 items-center justify-center"> | ||
{feedbacks?.map((feedback, index) => ( | ||
<Feedback.Item | ||
key={index} | ||
active={active} | ||
setActive={setActive} | ||
{...feedback} | ||
/> | ||
))} | ||
</div> | ||
<CButton loading={isLoading} onClick={handleSubmitFeedback}> | ||
{t("feedback.submit")} | ||
</CButton> | ||
</div> | ||
</PopoverContent> | ||
</Popover> | ||
); | ||
}; | ||
|
||
type IFeedbackItem = IFeedbackType & { active: any; setActive: any }; | ||
|
||
Feedback.Item = ({ | ||
title, | ||
imageSrc, | ||
active, | ||
setActive, | ||
level, | ||
}: IFeedbackItem) => { | ||
const handleclick = () => { | ||
setActive(level); | ||
}; | ||
|
||
const isActive = active === level; | ||
|
||
return ( | ||
<TooltipProvider delayDuration={100}> | ||
<Tooltip> | ||
<TooltipTrigger asChild> | ||
<Button | ||
onClick={handleclick} | ||
className={cn( | ||
"rounded-full transition-all duration-25", | ||
isActive ? " !bg-blue-100" : "" | ||
)} | ||
size="icon" | ||
variant="outline" | ||
> | ||
<Image src={imageSrc} width={32} height={32} alt={title} /> | ||
</Button> | ||
</TooltipTrigger> | ||
<TooltipContent> | ||
<p>{title}</p> | ||
</TooltipContent> | ||
</Tooltip> | ||
</TooltipProvider> | ||
); | ||
}; | ||
|
||
export default Feedback; |
63 changes: 63 additions & 0 deletions
63
apps/next/src/components/Layout/Dashboard/DashboardHeader/Navigation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import homeSidebarNavigations from "./navigation.constant"; | ||
import { cn } from "@wordigo/ui/lib/utils"; | ||
import Link from "next/link"; | ||
|
||
const Navigation = ({ variant }: { variant?: "borgerMenu" }) => { | ||
const classes = cn( | ||
"w-full", | ||
variant === "borgerMenu" ? "flex-col flex" : "flex items-center gap-3" | ||
); | ||
|
||
return ( | ||
<ul className="flex items-center font-sm mt-1 w-full"> | ||
<li className={cn(classes)}> | ||
<Navigation.Item variant={variant} /> | ||
</li> | ||
</ul> | ||
); | ||
}; | ||
|
||
Navigation.Item = ({ variant }: { variant: string }) => { | ||
const navigations = homeSidebarNavigations(); | ||
|
||
const checkActive = (href: string) => { | ||
if (typeof window !== "undefined") { | ||
if (href.includes("#")) { | ||
href = href.split("#")[0]; | ||
} | ||
|
||
return window.location.pathname === href; | ||
} | ||
return false; | ||
}; | ||
|
||
const classes_hover = cn( | ||
variant === "borgerMenu" ?? | ||
"hover:text-foreground text-muted-foreground flex item-center" | ||
); | ||
|
||
return ( | ||
<> | ||
{navigations.map((item, index) => [ | ||
<Link | ||
href={item.href} | ||
passHref | ||
key={index} | ||
className={cn( | ||
"flex items-center w-full transition-colors text-muted-foreground text-sm hover:text-accent-foreground font-medium group relative", | ||
variant === "borgerMenu" && | ||
"p-3 rounded-[6px] hover:bg-[#F8FAFC] dark:hover:bg-[#101929] mb-1", | ||
classes_hover, | ||
checkActive(item.href) && | ||
"text-accent-foreground bg-[#F8FAFC] dark:bg-[#101929] md:bg-transparent md:dark:bg-transparent md:text-muted-foreground md:dark:text-muted-foreground md:group-hover:bg-transparent md:group-hover:dark:bg-transparent md:group-hover:text-accent-foreground md:group-hover:dark:text-accent-foreground" | ||
)} | ||
> | ||
{item.icon} | ||
{item.title} | ||
</Link>, | ||
])} | ||
</> | ||
); | ||
}; | ||
|
||
export default Navigation; |
156 changes: 156 additions & 0 deletions
156
apps/next/src/components/Layout/Dashboard/DashboardHeader/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import NavProfile from "../../NavProfile"; | ||
import ThemeMode from "../../ThemeMode"; | ||
import Feedback from "./Feedback"; | ||
import Navigation from "./Navigation"; | ||
import DashboardHeader from "@/components/Layout/Dashboard/DashboardHeader"; | ||
import DashboardNavigation from "@/components/Layout/Dashboard/Sidebar/Navigation"; | ||
import ChangeLanguage from "@/components/Layout/MainLayout/ChangeLanguage"; | ||
import DynamicLogo from "@/components/Logo/DynamicLogo"; | ||
import StaticLogo from "@/components/Logo/StaticLogo"; | ||
import { Button, Separator, buttonVariants } from "@wordigo/ui"; | ||
import { cn } from "@wordigo/ui/lib/utils"; | ||
import { AnimatePresence, motion } from "framer-motion"; | ||
import { Menu, X } from "lucide-react"; | ||
import { useSession } from "next-auth/react"; | ||
import { useTranslation } from "next-i18next"; | ||
import Link from "next/link"; | ||
import { Fragment, useState } from "react"; | ||
|
||
export default function HomeHeader({ className }: { className?: string }) { | ||
const { t } = useTranslation(); | ||
const { status } = useSession(); | ||
|
||
const [isMenuOpen, setMenuOpen] = useState(false); | ||
|
||
const toggleMenu = () => { | ||
setMenuOpen(!isMenuOpen); | ||
}; | ||
|
||
return ( | ||
<> | ||
<div | ||
className={cn( | ||
"w-full fixed max-w-[90rem] bg-LightBackground dark:bg-DarkBackground z-50", | ||
className | ||
)} | ||
> | ||
<nav className="flex items-center justify-between w-full m-auto py-[1.125rem] px-20 max-md:px-4 max-8xl:px-5"> | ||
<div className="flex items-center"> | ||
<Link | ||
href="/" | ||
className={cn( | ||
"flex items-center mr-6 justify-center", | ||
!toggleMenu && "hidden" | ||
)} | ||
> | ||
<StaticLogo /> | ||
<div className="font-semibold ml-[10px]">Wordigo</div> | ||
</Link> | ||
<span className="max-lg:hidden"> | ||
<Navigation /> | ||
</span> | ||
</div> | ||
<div className="flex gap-x-4 items-center max-lg:hidden"> | ||
{status === "loading" ? ( | ||
<NavProfile.Loader /> | ||
) : status === "authenticated" ? ( | ||
<Fragment> | ||
<Feedback /> | ||
<div className="hidden md:block w-[0.5px] h-7 bg-gray-300 dark:bg-gray-700"></div> | ||
<NavProfile /> | ||
</Fragment> | ||
) : ( | ||
<div className="flex gap-y-6 gap-x-3 items-center"> | ||
<ThemeMode showLabel={false} className="!h-9 !px-3 !py-2" /> | ||
<ChangeLanguage className="!h-9 !px-3 !py-2" /> | ||
<div className="w-[1px] !h-9 bg-gray-200 dark:bg-gray-800"></div> | ||
<Link | ||
href="/auth/signup" | ||
className={cn( | ||
buttonVariants({ variant: "default", className: "!h-9" }) | ||
)} | ||
> | ||
{t("navbar.get_started")} | ||
</Link> | ||
</div> | ||
)} | ||
</div> | ||
<Button | ||
onClick={toggleMenu} | ||
className="lg:hidden text-black bg-transparent bg-white" | ||
variant="outline" | ||
size="icon" | ||
> | ||
<Menu size={17} /> | ||
</Button> | ||
</nav> | ||
</div> | ||
<AnimatePresence> | ||
{isMenuOpen && ( | ||
<motion.div | ||
initial={{ x: "100%" }} | ||
animate={{ x: 0 }} | ||
exit={{ x: "100%" }} | ||
transition={{ duration: 0.3, ease: "easeInOut" }} | ||
className="col-span-1 flex flex-col fixed justify-between top-0 right-0 z-50 py-4 text-light_text dark:text-white bg-LightBackground dark:bg-DarkBackground g-red-500 px-5 min-w-[280px] max-w-[280px] border-l shadow-md shadow-[rgba(16, 24, 40, 1)] h-screen lg:hidden z-50" | ||
> | ||
<span className="flex items-center flex-col w-full mb-8"> | ||
<div className="font-bold text-[18px] flex items-center select-none pt-3 justify-between w-full"> | ||
<Link | ||
href="/" | ||
className={cn( | ||
"flex items-center mr-6 max-w-[128px] min-w-[128px]", | ||
!toggleMenu && "hidden" | ||
)} | ||
> | ||
<DynamicLogo size={128} /> | ||
</Link> | ||
<Button | ||
onClick={toggleMenu} | ||
className="text-black dark:text-white !h-9 !w-9" | ||
variant="outline" | ||
size="icon" | ||
> | ||
<X size={19} /> | ||
</Button> | ||
</div> | ||
|
||
<div className="flex w-full md:flex-col py-4"> | ||
<DashboardNavigation /> | ||
</div> | ||
</span> | ||
|
||
<div className="lg:hidden"> | ||
<Separator className="mb-2" /> | ||
<div className="flex gap-x-4 items-center"> | ||
{status === "loading" ? ( | ||
<NavProfile.Loader /> | ||
) : status === "authenticated" ? ( | ||
<NavProfile variant="borgerMenu" /> | ||
) : ( | ||
<span className="w-full flex flex-col gap-y-3"> | ||
<div className="flex gap-x-2 items-center justify-between"> | ||
<ThemeMode className="!h-8 !px-2 w-full" /> | ||
<ChangeLanguage className="!h-8 !px-2 w-full" /> | ||
</div> | ||
<Link | ||
href="/auth/signup" | ||
className={cn( | ||
buttonVariants({ | ||
variant: "default", | ||
className: "w-full", | ||
}) | ||
)} | ||
> | ||
{t("navbar.get_started")} | ||
</Link> | ||
</span> | ||
)} | ||
</div> | ||
</div> | ||
</motion.div> | ||
)} | ||
</AnimatePresence> | ||
</> | ||
); | ||
} |
Oops, something went wrong.