This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-B2B/src/app/[locale]/(portal)/members/import/page.tsx
kirukib 3778801ef5 Ship Gishen B2B institutional portal with polished layout and mock-backed flows.
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>
2026-08-06 21:18:23 +03:00

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>
);
}