From 34277fcbe906c620865ad47590c1a8285e25af31 Mon Sep 17 00:00:00 2001 From: Sahaj Jain Date: Thu, 24 Apr 2025 23:57:18 +0530 Subject: [PATCH] update dashbaord UI --- app/dashboard/components/themes-list.tsx | 105 +++++++++++++++++++++++ app/dashboard/page.tsx | 88 ++++++++++++++----- components/ui/button.tsx | 4 +- 3 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 app/dashboard/components/themes-list.tsx diff --git a/app/dashboard/components/themes-list.tsx b/app/dashboard/components/themes-list.tsx new file mode 100644 index 00000000..6ef73898 --- /dev/null +++ b/app/dashboard/components/themes-list.tsx @@ -0,0 +1,105 @@ +"use client"; + +import { useState, useEffect } from "react"; +import type { Theme } from "@/types/theme"; +import { ThemeCard } from "./theme-card"; +import { Search, ArrowUpDown, Layers } from "lucide-react"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { useIsMobile } from "@/hooks/use-mobile"; + +interface ThemesListProps { + themes: Theme[]; + totalCount: number; +} + +export function ThemesList({ themes, totalCount }: ThemesListProps) { + const [filteredThemes, setFilteredThemes] = useState(themes); + const [searchTerm, setSearchTerm] = useState(""); + const [sortOption, setSortOption] = useState("newest"); + const isMobile = useIsMobile(); + + useEffect(() => { + const filtered = themes.filter((theme) => + theme.name?.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + // Sort based on selected option + const sorted = [...filtered].sort((a, b) => { + switch (sortOption) { + case "newest": + return (b.createdAt?.getTime() || 0) - (a.createdAt?.getTime() || 0); + case "oldest": + return (a.createdAt?.getTime() || 0) - (b.createdAt?.getTime() || 0); + case "name": + return (a.name || "").localeCompare(b.name || ""); + default: + return 0; + } + }); + + setFilteredThemes(sorted); + }, [themes, searchTerm, sortOption]); + + return ( +
+
+
+
+
+ + {totalCount} + + total themes + +
+
+
+
+ + setSearchTerm(e.target.value)} + /> +
+ +
+
+ + {filteredThemes.length === 0 && searchTerm ? ( +
+ +

No themes found

+

+ No themes match your search term "{searchTerm}" +

+
+ ) : ( +
+ {filteredThemes.map((theme: Theme) => ( + + ))} +
+ )} +
+
+ ); +} diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index ad1ca165..ee7a365c 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -1,10 +1,9 @@ -import { Theme } from "@/types/theme"; import { getThemes } from "@/actions/themes"; -import { ThemeCard } from "./components/theme-card"; import { Header } from "@/components/editor/header"; -import { Palette } from "lucide-react"; +import { Palette, Plus } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; +import { ThemesList } from "@/app/dashboard/components/themes-list"; export default async function ProfilePage() { const themes = await getThemes(); @@ -12,32 +11,75 @@ export default async function ProfilePage() { return b.createdAt?.getTime() - a.createdAt?.getTime(); }); + const oneWeekAgo = new Date(); + oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); + const recentThemeObjects = themes.filter((theme) => { + return theme.createdAt && theme.createdAt > oneWeekAgo; + }); + return ( - <> +
-
-

Your Themes

- {sortedThemes.length === 0 ? ( -
-
- -
-

No themes yet

-

- Create your first theme to get started +

+
+
+

Your Themes

+

+ Manage and explore your custom color themes

- - - +
+ + + +
+ + {sortedThemes.length === 0 ? ( +
+
+ +
+

+ No themes created yet +

+

+ Create your first custom theme to personalize your projects with + unique color palettes +

+
+ + + +
+
+ +
+
+ + or explore examples + +
+
+
+
+
+
+
+
) : ( -
- {sortedThemes.map((theme: Theme) => ( - - ))} -
+ )}
- +
); } diff --git a/components/ui/button.tsx b/components/ui/button.tsx index f0496e76..4c7522d6 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -11,7 +11,8 @@ const buttonVariants = cva( { variants: { variant: { - default: "bg-primary text-primary-foreground shadow hover:bg-primary/90", + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", outline: @@ -20,6 +21,7 @@ const buttonVariants = cva( "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", + accent: "bg-accent text-accent-foreground shadow-sm hover:bg-accent/80", }, size: { default: "h-9 px-4 py-2",