Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new dashboard #46

Merged
merged 3 commits into from
Oct 29, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function DataTableRowActions<TData extends object>({
}, [status]);

return (
<div className="w-full relative z-50">
<div className="w-full relative z-10">
{row.original.title !== "initial" && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
Expand Down
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;
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;
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 apps/next/src/components/Layout/Dashboard/DashboardHeader/index.tsx
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>
</>
);
}
Loading
Loading