From 48ac1d6f4dd1d8d4afce23dac9669e7a42b668d6 Mon Sep 17 00:00:00 2001 From: Ardeman Date: Sun, 23 Feb 2025 12:18:10 +0800 Subject: [PATCH] feat: add admin layout components including Navbar and Sidebar, and update icon components --- app/components/icons/cashier-machine.tsx | 23 ++++++++ app/components/icons/chart.tsx | 23 ++++++++ app/components/icons/chat.tsx | 23 ++++++++ app/components/icons/close.tsx | 2 +- app/components/icons/document.tsx | 23 ++++++++ app/components/icons/eye.tsx | 4 +- app/components/icons/medical-notes.tsx | 21 +++++++ app/components/icons/profile.tsx | 23 ++++++++ app/components/icons/setting.tsx | 23 ++++++++ app/components/icons/wallet.tsx | 23 ++++++++ app/layouts/admin/dashboard.tsx | 7 ++- app/layouts/admin/menu.ts | 73 ++++++++++++++++++++++++ app/layouts/admin/navbar.tsx | 3 + app/layouts/admin/sidebar.tsx | 25 ++++++++ app/layouts/news/menu.ts | 29 +++++----- 15 files changed, 307 insertions(+), 18 deletions(-) create mode 100644 app/components/icons/cashier-machine.tsx create mode 100644 app/components/icons/chart.tsx create mode 100644 app/components/icons/chat.tsx create mode 100644 app/components/icons/document.tsx create mode 100644 app/components/icons/medical-notes.tsx create mode 100644 app/components/icons/profile.tsx create mode 100644 app/components/icons/setting.tsx create mode 100644 app/components/icons/wallet.tsx create mode 100644 app/layouts/admin/menu.ts create mode 100644 app/layouts/admin/navbar.tsx create mode 100644 app/layouts/admin/sidebar.tsx diff --git a/app/components/icons/cashier-machine.tsx b/app/components/icons/cashier-machine.tsx new file mode 100644 index 0000000..95d5819 --- /dev/null +++ b/app/components/icons/cashier-machine.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const CashierMachineIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/chart.tsx b/app/components/icons/chart.tsx new file mode 100644 index 0000000..c733d6c --- /dev/null +++ b/app/components/icons/chart.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const ChartIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/chat.tsx b/app/components/icons/chat.tsx new file mode 100644 index 0000000..711bd6f --- /dev/null +++ b/app/components/icons/chat.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const ChatIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/close.tsx b/app/components/icons/close.tsx index 4c56409..db8aa03 100644 --- a/app/components/icons/close.tsx +++ b/app/components/icons/close.tsx @@ -16,7 +16,7 @@ export const CloseIcon = ( fillRule="evenodd" clipRule="evenodd" d="M20 23.537l8.838 8.838a2.5 2.5 0 003.537-3.537L23.533 20l8.84-8.838a2.498 2.498 0 000-3.536 2.5 2.5 0 00-3.536 0L20 16.466l-8.838-8.838a2.5 2.5 0 10-3.537 3.533L16.467 20l-8.84 8.84a2.5 2.5 0 103.536 3.533L20 23.537z" - fill="#currentColor" + fill="currentColor" /> ) diff --git a/app/components/icons/document.tsx b/app/components/icons/document.tsx new file mode 100644 index 0000000..87ffd37 --- /dev/null +++ b/app/components/icons/document.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const DocumentIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/eye.tsx b/app/components/icons/eye.tsx index 73cd4b8..ab300e4 100644 --- a/app/components/icons/eye.tsx +++ b/app/components/icons/eye.tsx @@ -8,13 +8,13 @@ export const EyeIcon = ( width={28} height={20} viewBox="0 0 28 20" - fill="currentColor" + fill="none" xmlns="http://www.w3.org/2000/svg" {...properties} > ) diff --git a/app/components/icons/medical-notes.tsx b/app/components/icons/medical-notes.tsx new file mode 100644 index 0000000..610fa2d --- /dev/null +++ b/app/components/icons/medical-notes.tsx @@ -0,0 +1,21 @@ +import type { JSX, SVGProps } from 'react' + +export const MedicalNotesIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/profile.tsx b/app/components/icons/profile.tsx new file mode 100644 index 0000000..240c438 --- /dev/null +++ b/app/components/icons/profile.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const ProfileIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/setting.tsx b/app/components/icons/setting.tsx new file mode 100644 index 0000000..8a818fd --- /dev/null +++ b/app/components/icons/setting.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const SettingIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/components/icons/wallet.tsx b/app/components/icons/wallet.tsx new file mode 100644 index 0000000..262faf4 --- /dev/null +++ b/app/components/icons/wallet.tsx @@ -0,0 +1,23 @@ +import type { JSX, SVGProps } from 'react' + +export const WalletIcon = ( + properties: JSX.IntrinsicAttributes & SVGProps, +) => { + return ( + + + + ) +} diff --git a/app/layouts/admin/dashboard.tsx b/app/layouts/admin/dashboard.tsx index d56830c..4398ee9 100644 --- a/app/layouts/admin/dashboard.tsx +++ b/app/layouts/admin/dashboard.tsx @@ -1,12 +1,15 @@ import type { PropsWithChildren } from 'react' +import { Navbar } from './navbar' +import { Sidebar } from './sidebar' + export const AdminDashboardLayout = (properties: PropsWithChildren) => { const { children } = properties return (
-
Navbar
+
-
Sidebar
+
{children}
diff --git a/app/layouts/admin/menu.ts b/app/layouts/admin/menu.ts new file mode 100644 index 0000000..7ef6deb --- /dev/null +++ b/app/layouts/admin/menu.ts @@ -0,0 +1,73 @@ +import type { JSX, SVGProps } from 'react' + +import { ChartIcon } from '~/components/icons/chart' +import { ChatIcon } from '~/components/icons/chat' +import { DocumentIcon } from '~/components/icons/document' +import { MedicalNotesIcon } from '~/components/icons/medical-notes' +import { ProfileIcon } from '~/components/icons/profile' +import { SettingIcon } from '~/components/icons/setting' +import { WalletIcon } from '~/components/icons/wallet' + +type TMenu = { + group: string + items: { + title: string + url: string + icon: ( + properties: JSX.IntrinsicAttributes & SVGProps, + ) => JSX.Element + }[] +} + +export const MENU: TMenu[] = [ + { + group: 'Menu', + items: [ + { + title: 'Dashboard', + url: '/admin/dashboard', + icon: ChartIcon, + }, + { + title: 'User', + url: '/admin/dashboard/users', + icon: DocumentIcon, + }, + { + title: 'Konten', + url: '/admin/dashboard/contents', + icon: ChatIcon, + }, + { + title: 'Advertisement', + url: '/admin/dashboard/advertisements', + icon: MedicalNotesIcon, + }, + { + title: 'Subscription', + url: '/admin/dashboard/subscriptions', + icon: ChartIcon, + }, + ], + }, + { + group: 'Others', + items: [ + { + title: 'Data Situs', + url: '/admin/dashboard/site-data', + icon: WalletIcon, + }, + { + title: 'Pengaturan', + url: '/admin/dashboard/settings', + icon: SettingIcon, + }, + { + title: 'Admin', + url: '/admin/dashboard/admins', + icon: ProfileIcon, + }, + ], + }, +] diff --git a/app/layouts/admin/navbar.tsx b/app/layouts/admin/navbar.tsx new file mode 100644 index 0000000..dbf19f6 --- /dev/null +++ b/app/layouts/admin/navbar.tsx @@ -0,0 +1,3 @@ +export const Navbar = () => { + return
Navbar
+} diff --git a/app/layouts/admin/sidebar.tsx b/app/layouts/admin/sidebar.tsx new file mode 100644 index 0000000..947f409 --- /dev/null +++ b/app/layouts/admin/sidebar.tsx @@ -0,0 +1,25 @@ +import { Link } from 'react-router' + +import { MENU } from './menu' + +export const Sidebar = () => { + return ( +
+ {MENU.map(({ group, items }) => ( + <> +
{group}
+ {items.map(({ title, url, icon: Icon }) => ( + + + {title} + + ))} + + ))} +
+ ) +} diff --git a/app/layouts/news/menu.ts b/app/layouts/news/menu.ts index d042c14..0c41da0 100644 --- a/app/layouts/news/menu.ts +++ b/app/layouts/news/menu.ts @@ -5,7 +5,20 @@ import { InstagramIcon } from '~/components/icons/instagram' import { LinkedinIcon } from '~/components/icons/linkedin' import { XIcon } from '~/components/icons/x' -export const MENU = [ +type TMenu = { + title: string + url: string + icon?: ( + properties: JSX.IntrinsicAttributes & SVGProps, + ) => JSX.Element +} + +type TFooterMenu = { + group: string + items: TMenu[] +} + +export const MENU: TMenu[] = [ { title: 'Spotlight', url: '/news/category/spotlight', @@ -36,17 +49,7 @@ export const MENU = [ }, ] -type FooterMenu = { - group: string - items: Array<{ - title: string - url: string - icon?: ( - properties: JSX.IntrinsicAttributes & SVGProps, - ) => JSX.Element - }> -} -export const FOOTER_MENU: FooterMenu[] = [ +export const FOOTER_MENU: TFooterMenu[] = [ { group: 'About Us', items: [ @@ -124,7 +127,7 @@ export const FOOTER_MENU: FooterMenu[] = [ }, ] -export const COPYRIGHT_MENU = [ +export const COPYRIGHT_MENU: TMenu[] = [ { title: 'Privacy Policy', url: '/news/privacy-policy',