Compare commits
5 Commits
2b8d0604e0
...
e11f007eb1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e11f007eb1 | ||
|
|
e484af6e71 | ||
|
|
00bb4f99cb | ||
|
|
7334e07537 | ||
|
|
712b9155d2 |
21
app/components/icons/graph.tsx
Normal file
21
app/components/icons/graph.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import type { JSX, SVGProps } from 'react'
|
||||||
|
|
||||||
|
export const GraphIcon = (
|
||||||
|
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={29}
|
||||||
|
height={28}
|
||||||
|
viewBox="0 0 29 28"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...properties}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M19.383 2.499H9.471c-4.306 0-6.872 2.496-6.872 6.682v9.625c0 4.197 2.566 6.693 6.872 6.693h9.9c4.306 0 6.873-2.495 6.873-6.681V9.18c.012-4.186-2.555-6.682-6.86-6.682zM9.258 21.071c0 .472-.402.863-.887.863s-.887-.391-.887-.863v-2.38c0-.471.402-.863.887-.863s.887.392.887.863v2.38zm6.056 0c0 .472-.402.863-.887.863s-.887-.391-.887-.863V16.3c0-.471.402-.862.887-.862s.887.39.887.862v4.773zm6.057 0c0 .472-.403.863-.888.863s-.887-.391-.887-.863v-7.153c0-.471.402-.862.887-.862s.888.391.888.863v7.152zm0-10.787c0 .472-.403.863-.888.863s-.887-.391-.887-.863V9.17a23.266 23.266 0 01-11.012 6.164c-.071.023-.142.023-.213.023a.891.891 0 01-.864-.655.859.859 0 01.651-1.047 21.515 21.515 0 0010.35-5.876H17.03c-.485 0-.887-.391-.887-.863 0-.471.402-.862.887-.862h3.466c.048 0 .083.023.13.023.06.011.119.011.178.034.059.023.106.058.165.092.036.023.071.035.107.058.012.011.012.023.024.023.047.046.082.092.118.138.035.046.07.08.083.126.023.046.023.092.035.15.012.057.036.115.036.184 0 .011.011.023.011.034v3.37h-.011z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
21
app/components/icons/user-doctor.tsx
Normal file
21
app/components/icons/user-doctor.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import type { JSX, SVGProps } from 'react'
|
||||||
|
|
||||||
|
export const UserDoctorIcon = (
|
||||||
|
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={25}
|
||||||
|
height={28}
|
||||||
|
viewBox="0 0 25 28"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...properties}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12.714 14.364a6.821 6.821 0 006.822-6.822A6.821 6.821 0 0012.714.72a6.822 6.822 0 00-6.822 6.822 6.822 6.822 0 006.822 6.822zM6.32 23.318c0 .708.57 1.279 1.279 1.279s1.279-.57 1.279-1.28c0-.708-.57-1.278-1.28-1.278-.708 0-1.278.57-1.278 1.279zM17.83 16.1v2.612a4.27 4.27 0 013.41 4.178v2.223a.855.855 0 01-.687.837l-1.716.34a.424.424 0 01-.501-.335l-.165-.837a.422.422 0 01.336-.5l1.028-.209v-1.519c0-3.347-5.116-3.47-5.116.102v1.423l1.028.207c.23.048.379.272.336.502l-.165.836a.432.432 0 01-.501.336l-1.663-.224a.852.852 0 01-.736-.847V22.89a4.274 4.274 0 013.412-4.178v-2.41c-.118.038-.235.06-.352.102a9.244 9.244 0 01-3.06.522c-1.07 0-2.1-.186-3.059-.522a5.889 5.889 0 00-1.204-.277v4.349a2.974 2.974 0 012.132 2.846 2.987 2.987 0 01-2.985 2.985 2.987 2.987 0 01-2.985-2.985c0-1.348.901-2.478 2.132-2.846v-4.285c-3.39.57-5.974 3.49-5.974 7.04v2.388a2.39 2.39 0 002.387 2.388h19.102a2.39 2.39 0 002.388-2.388v-2.388c0-3.837-3.028-6.944-6.822-7.13z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
31
app/components/ui/card-report.tsx
Normal file
31
app/components/ui/card-report.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { GraphIcon } from '~/components/icons/graph'
|
||||||
|
import { formatNumberWithPeriods } from '~/utils/formatter'
|
||||||
|
|
||||||
|
interface CardReportProperty {
|
||||||
|
title: string
|
||||||
|
amount: number
|
||||||
|
url?: string
|
||||||
|
type?: 'history' | 'report'
|
||||||
|
counter?: number[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CardReport = (properties: CardReportProperty) => {
|
||||||
|
const { title, amount } = properties
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex items-center rounded bg-white px-4 py-6 shadow-sm">
|
||||||
|
<GraphIcon
|
||||||
|
className="ml-2 rounded-xl bg-[#2E2F7C] p-2 text-white"
|
||||||
|
height={48}
|
||||||
|
width={48}
|
||||||
|
/>
|
||||||
|
<div className="ml-10">
|
||||||
|
<h2 className="text-lg font-semibold">{title}</h2>
|
||||||
|
<p className="text-2xl font-bold text-[#2E2F7C]">
|
||||||
|
Rp. {formatNumberWithPeriods(amount)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ const loginSchema = z.object({
|
|||||||
password: z.string().min(6, 'Kata sandi minimal 6 karakter'),
|
password: z.string().min(6, 'Kata sandi minimal 6 karakter'),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type TLoginSchema = z.infer<typeof loginSchema>
|
type TLoginSchema = z.infer<typeof loginSchema>
|
||||||
|
|
||||||
type TProperties = {
|
type TProperties = {
|
||||||
setIsRegisterOpen: Dispatch<SetStateAction<boolean>>
|
setIsRegisterOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
|||||||
20
app/pages/dashboard/data.ts
Normal file
20
app/pages/dashboard/data.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export const REPORT = [
|
||||||
|
{ title: 'Total Transaksi', amount: 10_800_000_000, icon: 'money' },
|
||||||
|
{ title: 'Transaksi Tertagih', amount: 2_000_000, icon: 'money' },
|
||||||
|
{ title: 'Transaksi Tertagih', amount: 2_000_000, icon: 'money' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const HISTORY = [
|
||||||
|
{
|
||||||
|
title: 'Total Kunjungan',
|
||||||
|
total: 1_000_000,
|
||||||
|
icon: 'money',
|
||||||
|
counter: [2190, 700],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Total User Memesan',
|
||||||
|
total: 274,
|
||||||
|
icon: 'money',
|
||||||
|
counter: [211, 54],
|
||||||
|
},
|
||||||
|
]
|
||||||
90
app/pages/dashboard/index.tsx
Normal file
90
app/pages/dashboard/index.tsx
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { GraphIcon } from '~/components/icons/graph'
|
||||||
|
import { CardReport } from '~/components/ui/card-report'
|
||||||
|
|
||||||
|
import { REPORT } from './data'
|
||||||
|
export const DashboardPage = () => {
|
||||||
|
return (
|
||||||
|
<div className="relative">
|
||||||
|
<div className="container mx-auto">
|
||||||
|
<section className="mb-5 flex items-center justify-between">
|
||||||
|
<h1 className="text-xl font-bold">Dashboard</h1>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span>Tanggal:</span>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded border p-2"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="rounded border p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div className="mb-5 grid grid-cols-3 gap-4">
|
||||||
|
{REPORT.map(({ title, amount }, index) => (
|
||||||
|
<CardReport
|
||||||
|
key={index}
|
||||||
|
title={title}
|
||||||
|
amount={amount}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 gap-x-4 gap-y-4">
|
||||||
|
<div className="grid gap-y-4">
|
||||||
|
<div className="rounded-lg bg-white p-5 shadow">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<GraphIcon
|
||||||
|
className="ml-2 rounded-xl bg-[#2E2F7C] p-2 text-white"
|
||||||
|
height={48}
|
||||||
|
width={48}
|
||||||
|
/>
|
||||||
|
<div className="ml-10">
|
||||||
|
<h2 className="text-lg font-semibold">Total Kunjungan</h2>
|
||||||
|
<p className="text-3xl font-bold text-[#2E2F7C]">2.890</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="pt-2">Pribadi: 2.190 | Perusahaan: 700</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg bg-white p-5 shadow">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<GraphIcon
|
||||||
|
className="ml-2 rounded-xl bg-[#2E2F7C] p-2 text-white"
|
||||||
|
height={48}
|
||||||
|
width={48}
|
||||||
|
/>
|
||||||
|
<div className="ml-10">
|
||||||
|
<h2 className="text-lg font-semibold">Total User Memesan</h2>
|
||||||
|
<p className="text-3xl font-bold text-[#2E2F7C]">274</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="pt-2">Pribadi: 211 | Perusahaan: 54</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<img
|
||||||
|
src="/images/dummy-chart-2.svg"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-5 flex justify-between gap-5">
|
||||||
|
<div className="w-[600px] shadow-sm">
|
||||||
|
<img
|
||||||
|
src="/images/dummy-chart-1.svg"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-[480px] shadow-sm">
|
||||||
|
<img
|
||||||
|
src="/images/dummy-chart-3.svg"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
|
import { DashboardPage } from '~/pages/dashboard'
|
||||||
|
|
||||||
const DashboardIndexLayout = () => {
|
const DashboardIndexLayout = () => {
|
||||||
return <div>Dashboard Page</div>
|
return <DashboardPage />
|
||||||
}
|
}
|
||||||
export default DashboardIndexLayout
|
export default DashboardIndexLayout
|
||||||
|
|||||||
3
app/utils/formatter.ts
Normal file
3
app/utils/formatter.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const formatNumberWithPeriods = (number: number) => {
|
||||||
|
return new Intl.NumberFormat('id-ID').format(number)
|
||||||
|
}
|
||||||
39
public/images/dummy-chart-1.svg
Normal file
39
public/images/dummy-chart-1.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 50 KiB |
103
public/images/dummy-chart-2.svg
Normal file
103
public/images/dummy-chart-2.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 75 KiB |
18
public/images/dummy-chart-3.svg
Normal file
18
public/images/dummy-chart-3.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 38 KiB |
Loading…
x
Reference in New Issue
Block a user