Deliver role-aware shell (sidebar, breadcrumbs, quick search, tables, detail/create layouts), locale-ready pages, shared backend/feature docs, and Vercel project config so HR, finance, and members can demo against typed mocks. Co-authored-by: Cursor <cursoragent@cursor.com>
126 lines
4.6 KiB
TypeScript
126 lines
4.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { useTranslations } from "next-intl";
|
|
import { toast } from "sonner";
|
|
import { CreatePageLayout } from "@/components/layout/create-layout";
|
|
import { Link } from "@/i18n/routing";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { TablePanel } from "@/components/table/table-panel";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import { ArrowLeft, Download, Upload } from "lucide-react";
|
|
|
|
type Step = "upload" | "preview";
|
|
|
|
const PREVIEW_ROWS = [
|
|
{ employeeId: "YT-1201", name: "Tigist Alemu", department: "Engineering", package: "Gold Corporate" },
|
|
{ employeeId: "YT-1202", name: "Biniam Tesfaye", department: "Sales", package: "Silver Standard" },
|
|
{ employeeId: "YT-1203", name: "Hanna Bekele", department: "Operations", package: "Bronze Essentials" },
|
|
];
|
|
|
|
export default function MembersImportPage() {
|
|
const t = useTranslations();
|
|
const [step, setStep] = useState<Step>("upload");
|
|
const [fileName, setFileName] = useState<string | null>(null);
|
|
|
|
function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
const file = e.target.files?.[0];
|
|
if (file) {
|
|
setFileName(file.name);
|
|
setStep("preview");
|
|
}
|
|
}
|
|
|
|
function handleImport() {
|
|
toast.success(t("common.pending"));
|
|
}
|
|
|
|
return (
|
|
<CreatePageLayout
|
|
title={t("members.importTitle")}
|
|
description={t("members.importSubtitle")}
|
|
extra={
|
|
<Button variant="outline" className="gap-2" render={<Link href="/members" />}>
|
|
<ArrowLeft className="size-4" />
|
|
{t("common.back")}
|
|
</Button>
|
|
}
|
|
>
|
|
<div className="space-y-4">
|
|
<div className="flex flex-wrap gap-2">
|
|
<Badge variant={step === "upload" ? "default" : "secondary"}>1. {t("common.upload")}</Badge>
|
|
<Badge variant={step === "preview" ? "default" : "secondary"}>2. {t("common.preview")}</Badge>
|
|
</div>
|
|
|
|
{step === "upload" && (
|
|
<Card className="rounded-2xl shadow-none">
|
|
<CardHeader>
|
|
<CardTitle className="text-base">{t("common.upload")}</CardTitle>
|
|
<CardDescription>Upload an Excel file or download the template first.</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<Button variant="outline" className="gap-2" onClick={() => toast.info(t("common.template"))}>
|
|
<Download className="size-4" />
|
|
{t("common.template")}
|
|
</Button>
|
|
<div className="flex items-center gap-3">
|
|
<Input type="file" accept=".xlsx,.xls,.csv" onChange={handleFileChange} />
|
|
<Upload className="size-5 shrink-0 text-muted-foreground" />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{step === "preview" && fileName && (
|
|
<div className="space-y-4">
|
|
<div className="space-y-1">
|
|
<p className="text-sm font-semibold text-foreground">{t("common.preview")}</p>
|
|
<p className="text-sm text-muted-foreground">
|
|
{fileName} — 3 rows ready to import
|
|
</p>
|
|
</div>
|
|
<TablePanel>
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>{t("members.employeeId")}</TableHead>
|
|
<TableHead>Name</TableHead>
|
|
<TableHead>{t("members.department")}</TableHead>
|
|
<TableHead>{t("members.package")}</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{PREVIEW_ROWS.map((row) => (
|
|
<TableRow key={row.employeeId}>
|
|
<TableCell className="font-mono text-xs">{row.employeeId}</TableCell>
|
|
<TableCell>{row.name}</TableCell>
|
|
<TableCell>{row.department}</TableCell>
|
|
<TableCell>{row.package}</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TablePanel>
|
|
<div className="flex gap-2">
|
|
<Button variant="outline" onClick={() => setStep("upload")}>
|
|
{t("common.back")}
|
|
</Button>
|
|
<Button onClick={handleImport}>{t("common.submit")}</Button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CreatePageLayout>
|
|
);
|
|
}
|