Skip to content

Commit

Permalink
feat: adjust admin dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
zekhoi committed Aug 31, 2024
1 parent a2ac0be commit af2dfa6
Show file tree
Hide file tree
Showing 20 changed files with 306 additions and 186 deletions.
8 changes: 8 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ const nextConfig = {
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '*.googleusercontent.com',
},
],
},
};

export default nextConfig;
29 changes: 29 additions & 0 deletions src/app/(private)/dashboard/(admin)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Metadata } from 'next';
import { redirect } from 'next/navigation';

import { checkAdmin } from '@/lib/auth';

export const metadata: Metadata = {
title: 'Dashboard | Sainseni Community',
authors: [
{
name: 'Khoironi Kurnia Syah',
url: 'https://zekhoi.dev',
},
],
description: 'Community for community',
};

export default async function PrivateLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const { isAdmin } = await checkAdmin();

if (!isAdmin) {
return redirect('/dashboard');
}

return <>{children}</>;
}
148 changes: 66 additions & 82 deletions src/app/(private)/dashboard/(admin)/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useGetRoles } from '@/lib/queries';
import { useGetUsers } from '@/lib/queries/users.query';

import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area';
import {
Select,
Expand All @@ -26,7 +26,7 @@ import {
} from '@/components/ui/table';
import { useToast } from '@/components/ui/use-toast';

import RoleFormDialog from './role-form';
import RoleFormDialog from './role-form-dialog';

export default function UserManagement() {
const { toast } = useToast();
Expand Down Expand Up @@ -92,92 +92,76 @@ export default function UserManagement() {
}

return (
<div className='container mx-auto p-4 space-y-8'>
<header className='flex flex-col sm:flex-row justify-between items-start sm:items-center space-y-4 sm:space-y-0'>
<Card>
<CardHeader className='flex flex-col sm:flex-row justify-between items-start sm:items-center space-y-4 sm:space-y-0'>
<h1 className='text-2xl font-bold flex items-center gap-2'>
<Users className='h-6 w-6' />
User Management
Users
</h1>
<div className='flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2 w-full sm:w-auto'>
<RoleFormDialog />
</div>
</header>

<main>
<Card>
<CardHeader>
<CardTitle>User List</CardTitle>
</CardHeader>
<CardContent>
<ScrollArea className='h-[300px] sm:h-[400px]'>
<Table>
<TableHeader>
<TableRow>
<TableHead className='w-[200px]'>
Name
</TableHead>
<TableHead className='hidden sm:table-cell'>
Email
</TableHead>
<TableHead>Role</TableHead>
</CardHeader>
<CardContent>
<ScrollArea className='h-[300px] sm:h-[400px]'>
<Table>
<TableHeader>
<TableRow>
<TableHead className='w-[200px]'>
Name
</TableHead>
<TableHead className='hidden sm:table-cell'>
Email
</TableHead>
<TableHead>Role</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{userData &&
userData.map((user) => (
<TableRow key={user.id}>
<TableCell className='font-medium'>
{user.name}
</TableCell>
<TableCell className='hidden sm:table-cell'>
{user.email}
</TableCell>
<TableCell>
<Select
defaultValue={user.roleId}
onValueChange={(value) =>
handleRoleChange(
user.id,
value,
)
}
disabled={
editUserRoleMutation.isPending
}
>
<SelectTrigger className='w-[180px]'>
<SelectValue placeholder='Select a role' />
</SelectTrigger>
<SelectContent>
{roleData &&
roleData.map((role) => (
<SelectItem
className='focus-visible:ring-0'
key={role.id}
value={role.id}
>
{role.name}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{userData &&
userData.map((user) => (
<TableRow key={user.id}>
<TableCell className='font-medium'>
{user.name}
</TableCell>
<TableCell className='hidden sm:table-cell'>
{user.email}
</TableCell>
<TableCell>
<Select
defaultValue={
user.roleId
}
onValueChange={(
value,
) =>
handleRoleChange(
user.id,
value,
)
}
>
<SelectTrigger className='w-[180px]'>
<SelectValue placeholder='Select a role' />
</SelectTrigger>
<SelectContent>
{roleData &&
roleData.map(
(role) => (
<SelectItem
key={
role.id
}
value={
role.id
}
>
{
role.name
}
</SelectItem>
),
)}
</SelectContent>
</Select>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
</CardContent>
</Card>
</main>
</div>
))}
</TableBody>
</Table>
</ScrollArea>
</CardContent>
</Card>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export default function RoleFormDialog() {
role.id,
)
}
className='w-1/2 focus-visible:ring-0'
className='w-1/2'
/>
) : (
<span>{role.name}</span>
Expand Down Expand Up @@ -259,7 +259,7 @@ export default function RoleFormDialog() {
handleCancelEdit
}
>
<X className='h-4 w-4' />
<X className='h-4 w-4 text-red-500' />
<span className='sr-only'>
Cancel
</span>
Expand Down Expand Up @@ -300,7 +300,7 @@ export default function RoleFormDialog() {
role.id ? (
<Loader2 className='h-4 w-4 animate-spin' />
) : (
<Trash2 className='h-4 w-4' />
<Trash2 className='h-4 w-4 text-red-500' />
)}
<span className='sr-only'>
Delete{' '}
Expand Down
Empty file.
8 changes: 4 additions & 4 deletions src/app/(private)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import {

export default function DashboardPage() {
return (
<div className='flex min-h-screen w-full flex-col'>
<main className='flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-8'>
<>
<div className='flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-8'>
<div className='grid gap-4 md:grid-cols-2 md:gap-8 lg:grid-cols-4'>
<Card x-chunk='dashboard-01-chunk-0'>
<CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
Expand Down Expand Up @@ -374,7 +374,7 @@ export default function DashboardPage() {
</CardContent>
</Card>
</div>
</main>
</div>
</div>
</>
);
}
5 changes: 3 additions & 2 deletions src/app/(private)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { redirect } from 'next/navigation';

import { checkAdmin, validateRequest } from '@/lib/auth';

import Container from '@/components/common/container';
import PrivateHeader from '@/components/private/header';

export const metadata: Metadata = {
Expand All @@ -27,12 +28,12 @@ export default async function PrivateLayout({
return redirect('/auth/signin');
}

const isAdmin = await checkAdmin();
const { isAdmin } = await checkAdmin();

return (
<div className='flex flex-col min-h-screen bg-white text-gray-800'>
<PrivateHeader isAdmin={isAdmin} userData={user} />
{children}
<Container>{children}</Container>
</div>
);
}
3 changes: 3 additions & 0 deletions src/components/common/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Container({ children }: { children: React.ReactNode }) {
return <main className='container mx-auto p-4 space-y-8'>{children}</main>;
}
Loading

0 comments on commit af2dfa6

Please sign in to comment.