feat: add GenderBadge and StudentStatusBadge components; update user columns to utilize new badges #46
25
resources/js/components/gender-badge.tsx
Normal file
25
resources/js/components/gender-badge.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
|
||||
type GenderBadgeProps = {
|
||||
gender: string | null | undefined;
|
||||
};
|
||||
|
||||
export function GenderBadge({ gender }: GenderBadgeProps) {
|
||||
if (gender === 'male') {
|
||||
return (
|
||||
<Badge className="bg-blue-100 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300">
|
||||
Laki-laki
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
if (gender === 'female') {
|
||||
return (
|
||||
<Badge className="bg-pink-100 text-pink-700 dark:bg-pink-500/20 dark:text-pink-300">
|
||||
Perempuan
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
return <span className="text-muted-foreground">-</span>;
|
||||
}
|
||||
34
resources/js/components/student-status-badge.tsx
Normal file
34
resources/js/components/student-status-badge.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
|
||||
type StudentStatusBadgeProps = {
|
||||
status: string | null | undefined;
|
||||
};
|
||||
|
||||
const StudentStatusLabels: Record<string, string> = {
|
||||
active: 'Aktif',
|
||||
on_leave: 'Cuti',
|
||||
graduated: 'Lulus',
|
||||
dropped_out: 'Drop Out',
|
||||
};
|
||||
|
||||
const StudentStatusVariants: Record<
|
||||
string,
|
||||
'default' | 'secondary' | 'destructive' | 'outline'
|
||||
> = {
|
||||
active: 'default',
|
||||
on_leave: 'secondary',
|
||||
graduated: 'outline',
|
||||
dropped_out: 'destructive',
|
||||
};
|
||||
|
||||
export function StudentStatusBadge({ status }: StudentStatusBadgeProps) {
|
||||
if (!status) {
|
||||
return <span className="text-muted-foreground">-</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge variant={StudentStatusVariants[status] ?? 'outline'}>
|
||||
{StudentStatusLabels[status] ?? status}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
import type { ColumnDef } from '@tanstack/react-table';
|
||||
import { Key, Pencil, Trash2 } from 'lucide-react';
|
||||
import { GenderBadge } from '@/components/gender-badge';
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
|
||||
export type Administrator = {
|
||||
id: number;
|
||||
@ -33,7 +34,9 @@ export function createAdministratorColumns(
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col">
|
||||
<span>{row.original.username}</span>
|
||||
<span className="text-sm text-muted-foreground">{row.original.email}</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{row.original.email}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@ -50,10 +53,9 @@ export function createAdministratorColumns(
|
||||
{
|
||||
accessorKey: 'profile.gender',
|
||||
header: () => <span>Jenis Kelamin</span>,
|
||||
cell: ({ row }) => {
|
||||
const gender = row.original.profile?.gender;
|
||||
return gender === 'male' ? 'Laki-laki' : gender === 'female' ? 'Perempuan' : '-';
|
||||
},
|
||||
cell: ({ row }) => (
|
||||
<GenderBadge gender={row.original.profile?.gender} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
@ -80,7 +82,9 @@ export function createAdministratorColumns(
|
||||
},
|
||||
{
|
||||
label: 'Hapus',
|
||||
icon: <Trash2 className="h-4 w-4 text-destructive" />,
|
||||
icon: (
|
||||
<Trash2 className="h-4 w-4 text-destructive" />
|
||||
),
|
||||
onClick: () => handleDeleteClick(admin),
|
||||
},
|
||||
]}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
import type { ColumnDef } from '@tanstack/react-table';
|
||||
import { Key, Pencil, Trash2 } from 'lucide-react';
|
||||
import { GenderBadge } from '@/components/gender-badge';
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
|
||||
export type Lecturer = {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
profile: { full_name: string } | null;
|
||||
lecturer: { lecturer_number: string; department: { name: string } | null } | null;
|
||||
profile: { full_name: string; phone_number: string; gender: string } | null;
|
||||
lecturer: {
|
||||
lecturer_number: string;
|
||||
department: { name: string } | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
type CreateColumnsParams = {
|
||||
@ -23,14 +27,16 @@ export function createLecturerColumns(
|
||||
|
||||
return [
|
||||
{
|
||||
accessorKey: 'lecturer.lecturer_number',
|
||||
id: 'identity',
|
||||
header: () => <span>NIDN</span>,
|
||||
cell: ({ row }) => row.original.lecturer?.lecturer_number ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.full_name',
|
||||
header: () => <span>Nama Lengkap</span>,
|
||||
cell: ({ row }) => row.original.profile?.full_name ?? '-',
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col">
|
||||
<span>{row.original.lecturer?.lecturer_number ?? '-'}</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{row.original.profile?.full_name ?? '-'}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'account',
|
||||
@ -38,7 +44,9 @@ export function createLecturerColumns(
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col">
|
||||
<span>{row.original.username}</span>
|
||||
<span className="text-sm text-muted-foreground">{row.original.email}</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{row.original.email}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@ -47,6 +55,18 @@ export function createLecturerColumns(
|
||||
header: () => <span>Jurusan</span>,
|
||||
cell: ({ row }) => row.original.lecturer?.department?.name ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.phone_number',
|
||||
header: () => <span>Nomor Telepon</span>,
|
||||
cell: ({ row }) => row.original.profile?.phone_number ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.gender',
|
||||
header: () => <span>Jenis Kelamin</span>,
|
||||
cell: ({ row }) => (
|
||||
<GenderBadge gender={row.original.profile?.gender} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
header: () => <span className="block text-center">Aksi</span>,
|
||||
@ -72,7 +92,9 @@ export function createLecturerColumns(
|
||||
},
|
||||
{
|
||||
label: 'Hapus',
|
||||
icon: <Trash2 className="h-4 w-4 text-destructive" />,
|
||||
icon: (
|
||||
<Trash2 className="h-4 w-4 text-destructive" />
|
||||
),
|
||||
onClick: () => handleDeleteClick(lecturer),
|
||||
},
|
||||
]}
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
import type { ColumnDef } from '@tanstack/react-table';
|
||||
import { Key, Pencil, Trash2 } from 'lucide-react';
|
||||
import { GenderBadge } from '@/components/gender-badge';
|
||||
import { RowActions } from '@/components/row-actions';
|
||||
import { StudentStatusBadge } from '@/components/student-status-badge';
|
||||
|
||||
export type Student = {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
profile: { full_name: string } | null;
|
||||
student: { student_number: string; department: { name: string } | null; enrollment_year: number; status: string | null } | null;
|
||||
profile: { full_name: string; phone_number: string; gender: string } | null;
|
||||
student: {
|
||||
student_number: string;
|
||||
department: { name: string } | null;
|
||||
enrollment_year: number;
|
||||
status: string | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
type CreateColumnsParams = {
|
||||
@ -23,14 +30,16 @@ export function createStudentColumns(
|
||||
|
||||
return [
|
||||
{
|
||||
accessorKey: 'student.student_number',
|
||||
id: 'identity',
|
||||
header: () => <span>NIM</span>,
|
||||
cell: ({ row }) => row.original.student?.student_number ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.full_name',
|
||||
header: () => <span>Nama Lengkap</span>,
|
||||
cell: ({ row }) => row.original.profile?.full_name ?? '-',
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col">
|
||||
<span>{row.original.student?.student_number ?? '-'}</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{row.original.profile?.full_name ?? '-'}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'account',
|
||||
@ -38,7 +47,9 @@ export function createStudentColumns(
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col">
|
||||
<span>{row.original.username}</span>
|
||||
<span className="text-sm text-muted-foreground">{row.original.email}</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{row.original.email}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@ -55,7 +66,21 @@ export function createStudentColumns(
|
||||
{
|
||||
accessorKey: 'student.status',
|
||||
header: () => <span>Status</span>,
|
||||
cell: ({ row }) => row.original.student?.status ?? '-',
|
||||
cell: ({ row }) => (
|
||||
<StudentStatusBadge status={row.original.student?.status} />
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.phone_number',
|
||||
header: () => <span>Nomor Telepon</span>,
|
||||
cell: ({ row }) => row.original.profile?.phone_number ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'profile.gender',
|
||||
header: () => <span>Jenis Kelamin</span>,
|
||||
cell: ({ row }) => (
|
||||
<GenderBadge gender={row.original.profile?.gender} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
@ -82,7 +107,9 @@ export function createStudentColumns(
|
||||
},
|
||||
{
|
||||
label: 'Hapus',
|
||||
icon: <Trash2 className="h-4 w-4 text-destructive" />,
|
||||
icon: (
|
||||
<Trash2 className="h-4 w-4 text-destructive" />
|
||||
),
|
||||
onClick: () => handleDeleteClick(student),
|
||||
},
|
||||
]}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user