Compare commits
No commits in common. "1cd5b0e848c69138a0f5d05ba2f8315c80f1f21d" and "2a0b0af45f9986d4b6f5867eed6a7945754eae8b" have entirely different histories.
1cd5b0e848
...
2a0b0af45f
@ -1,28 +0,0 @@
|
|||||||
import type { JSX, SVGProps } from 'react'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note: `ChevronDoubleIcon` default mengarah ke kiri.
|
|
||||||
* Gunakan class `rotate-xx` untuk mengubah arah ikon.
|
|
||||||
*/
|
|
||||||
export const ChevronDoubleIcon = (
|
|
||||||
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
width={20}
|
|
||||||
height={20}
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className={properties.className}
|
|
||||||
{...properties}
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M12.512 4.427l-2.984 3.58 2.877 3.575a.667.667 0 01-1.04.836l-3.218-4a.667.667 0 01.007-.844l3.334-4a.667.667 0 011.024.853zm-5.69-.853a.667.667 0 011.023.853l-2.984 3.58 2.877 3.575a.667.667 0 01-1.039.836l-3.218-4a.666.666 0 01.007-.844l3.333-4z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,9 +1,6 @@
|
|||||||
import type { JSX, SVGProps } from 'react'
|
import type { JSX, SVGProps } from 'react'
|
||||||
/**
|
|
||||||
* Note: `ChevronIcon` default mengarah ke bawah.
|
export const ChevronDownIcon = (
|
||||||
* Gunakan class `rotate-xx` untuk mengubah arah ikon.
|
|
||||||
*/
|
|
||||||
export const ChevronIcon = (
|
|
||||||
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
@ -13,7 +10,6 @@ export const ChevronIcon = (
|
|||||||
viewBox="0 0 21 21"
|
viewBox="0 0 21 21"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
className={properties.className}
|
|
||||||
{...properties}
|
{...properties}
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@ -1,66 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
import { ChevronIcon } from '~/components/icons/chevron'
|
|
||||||
import { ChevronDoubleIcon } from '~/components/icons/chevron-double'
|
|
||||||
|
|
||||||
interface PaginationProperties {
|
|
||||||
currentPage: number
|
|
||||||
totalPages: number
|
|
||||||
onPageChange: (page: number) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Pagination: React.FC<PaginationProperties> = ({
|
|
||||||
currentPage = 1,
|
|
||||||
totalPages,
|
|
||||||
onPageChange,
|
|
||||||
}) => {
|
|
||||||
const renderPageNumbers = () => {
|
|
||||||
const pages = []
|
|
||||||
for (let index = 1; index <= totalPages; index++) {
|
|
||||||
pages.push(
|
|
||||||
<button
|
|
||||||
key={index}
|
|
||||||
onClick={() => onPageChange(index)}
|
|
||||||
className={`rounded-lg px-3 py-1 ${
|
|
||||||
currentPage === index ? 'bg-[#2E2F7C] text-white' : 'text-gray-500'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{index}
|
|
||||||
</button>,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return pages
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex items-center justify-center space-x-2 text-[#2E2F7C]">
|
|
||||||
<button
|
|
||||||
onClick={() => onPageChange(1)}
|
|
||||||
disabled={currentPage === 1}
|
|
||||||
>
|
|
||||||
<ChevronDoubleIcon />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => onPageChange(currentPage - 1)}
|
|
||||||
disabled={currentPage === 1}
|
|
||||||
>
|
|
||||||
<ChevronIcon className="rotate-90" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{renderPageNumbers()}
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => onPageChange(currentPage + 1)}
|
|
||||||
disabled={currentPage === totalPages}
|
|
||||||
>
|
|
||||||
<ChevronIcon className="rotate-270" />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => onPageChange(totalPages)}
|
|
||||||
disabled={currentPage === totalPages}
|
|
||||||
>
|
|
||||||
<ChevronDoubleIcon className="rotate-180" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { Link } from 'react-router'
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import { ChevronIcon } from '~/components/icons/chevron'
|
import { ChevronDownIcon } from '~/components/icons/chevron-down'
|
||||||
import { NotificationIcon } from '~/components/icons/notification'
|
import { NotificationIcon } from '~/components/icons/notification'
|
||||||
import { useAdminContext } from '~/contexts/admin'
|
import { useAdminContext } from '~/contexts/admin'
|
||||||
import { APP } from '~/data/meta'
|
import { APP } from '~/data/meta'
|
||||||
@ -26,7 +26,7 @@ export const Navbar = () => {
|
|||||||
<div className="mr-3 h-8 w-8 rounded-full bg-[#C4C4C4]" />
|
<div className="mr-3 h-8 w-8 rounded-full bg-[#C4C4C4]" />
|
||||||
<span className="text-xs">{adminProfile.name}</span>
|
<span className="text-xs">{adminProfile.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<ChevronIcon className="opacity-50" />
|
<ChevronDownIcon className="opacity-10" />
|
||||||
</div>
|
</div>
|
||||||
<NotificationIcon
|
<NotificationIcon
|
||||||
className="text-[#B0C3CC]"
|
className="text-[#B0C3CC]"
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
type TUsers = {
|
|
||||||
id: number
|
|
||||||
idTransaction: number
|
|
||||||
date: string
|
|
||||||
name: string
|
|
||||||
email: string
|
|
||||||
category: string
|
|
||||||
status: string
|
|
||||||
}
|
|
||||||
export const USERS: TUsers[] = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
idTransaction: 5_512_446_588,
|
|
||||||
date: '24/10/2024',
|
|
||||||
name: 'Ainun Wijaya',
|
|
||||||
email: 'ainun@gmail.com',
|
|
||||||
category: 'Pribadi',
|
|
||||||
status: 'Baru',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
idTransaction: 5_512_446_588,
|
|
||||||
date: '24/10/2024',
|
|
||||||
name: 'Ainun Wijaya',
|
|
||||||
email: 'ainun@gmail.com',
|
|
||||||
category: 'Pribadi',
|
|
||||||
status: 'Premium',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
idTransaction: 5_512_446_588,
|
|
||||||
date: '24/10/2024',
|
|
||||||
name: 'Ainun Wijaya',
|
|
||||||
email: 'ainun@gmail.com',
|
|
||||||
category: 'Pribadi',
|
|
||||||
status: 'Pembayaran',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
idTransaction: 5_512_446_588,
|
|
||||||
date: '24/10/2024',
|
|
||||||
name: 'Ainun Wijaya',
|
|
||||||
email: 'ainun@gmail.com',
|
|
||||||
category: 'Pribadi',
|
|
||||||
status: 'Premium',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
idTransaction: 5_512_446_588,
|
|
||||||
date: '24/10/2024',
|
|
||||||
name: 'Ainun Wijaya',
|
|
||||||
email: 'ainun@gmail.com',
|
|
||||||
category: 'Pribadi',
|
|
||||||
status: 'Baru',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
import { Field, Input, Label, Select } from '@headlessui/react'
|
|
||||||
|
|
||||||
import { SearchIcon } from '~/components/icons/search'
|
|
||||||
import { Pagination } from '~/components/ui/pagination'
|
|
||||||
|
|
||||||
import { USERS } from './data'
|
|
||||||
|
|
||||||
type TColorBadge = 'Baru' | 'Premium' | 'Pembayaran'
|
|
||||||
|
|
||||||
export const UsersPage = () => {
|
|
||||||
const getStatusBadge = (status: TColorBadge) => {
|
|
||||||
const statusColors = {
|
|
||||||
Baru: 'bg-[#DFE5FF] text-[#4C5CA0]',
|
|
||||||
Premium: 'bg-[#FFFCAF] text-[#DBCA6E]',
|
|
||||||
Pembayaran: 'bg-[#FEC4FF] text-[#CC6EDB]',
|
|
||||||
}
|
|
||||||
return statusColors[status] || 'bg-gray-200 text-gray-700'
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<div className="container mx-auto">
|
|
||||||
<section className="mb-5 flex items-center justify-between">
|
|
||||||
<h1 className="text-xl font-bold">User</h1>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{/* filter section */}
|
|
||||||
|
|
||||||
<div className="mb-8 flex items-center gap-5 rounded-lg bg-gray-50 text-[#363636]">
|
|
||||||
<div className="w-[400px]">
|
|
||||||
<Field>
|
|
||||||
<Label className="mb-2 block text-sm font-medium">Cari User</Label>
|
|
||||||
<div className="relative">
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
placeholder="Cari Nama"
|
|
||||||
className="w-full rounded-lg bg-white p-2 pr-10 pl-4 shadow focus:ring-1 focus:ring-[#2E2F7C] focus:outline-none"
|
|
||||||
/>
|
|
||||||
<div className="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
||||||
<SearchIcon className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-[235px]">
|
|
||||||
<Field>
|
|
||||||
<Label className="mb-2 block text-sm font-medium">Status</Label>
|
|
||||||
<Select className="w-full rounded-lg bg-white p-2 shadow focus:ring-1 focus:ring-[#2E2F7C] focus:outline-none">
|
|
||||||
<option>Pilih Status</option>
|
|
||||||
<option>Aktif</option>
|
|
||||||
<option>Nonaktif</option>
|
|
||||||
</Select>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* table */}
|
|
||||||
<div className="overflow-x-auto">
|
|
||||||
<div className="rounded-lg bg-white px-6 py-8 shadow-sm">
|
|
||||||
<h2 className="text-xl font-bold text-[#4C5CA0]">Daftar User</h2>
|
|
||||||
<table className="min-w-full p-3">
|
|
||||||
<thead className="my-5 border-b-3 border-[#C2C2C2]">
|
|
||||||
<tr>
|
|
||||||
<th className="p-3">No</th>
|
|
||||||
<th>Tanggal Daftar</th>
|
|
||||||
<th>Nama User</th>
|
|
||||||
<th>Email</th>
|
|
||||||
<th>Kategori</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{USERS.map((user, index) => (
|
|
||||||
<tr
|
|
||||||
key={user.id}
|
|
||||||
className="border-b-1 border-gray-200 text-center"
|
|
||||||
>
|
|
||||||
<td className="p-4">{index + 1}</td>
|
|
||||||
<td>{user.date}</td>
|
|
||||||
<td>
|
|
||||||
{user.name}
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
id: {user.idTransaction}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>{user.email}</td>
|
|
||||||
<td>{user.category}</td>
|
|
||||||
<td className="">
|
|
||||||
<span
|
|
||||||
className={`inline-block min-w-[100px] rounded-full px-2 py-1 text-sm ${getStatusBadge(user.status as TColorBadge)}`}
|
|
||||||
>
|
|
||||||
{user.status}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* pagination */}
|
|
||||||
<div className="float-end mt-6">
|
|
||||||
<Pagination
|
|
||||||
currentPage={1}
|
|
||||||
totalPages={5}
|
|
||||||
onPageChange={() => {}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,6 +1,4 @@
|
|||||||
import { UsersPage } from '~/pages/dashboard-users'
|
|
||||||
|
|
||||||
const DashboardUsersLayout = () => {
|
const DashboardUsersLayout = () => {
|
||||||
return <UsersPage />
|
return <div>Users Page</div>
|
||||||
}
|
}
|
||||||
export default DashboardUsersLayout
|
export default DashboardUsersLayout
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user