summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-24 20:13:50 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-24 20:13:50 +0900
commitc54a2445b6285d06c0ce3afa1cd3aa6aecf6de94 (patch)
tree7a3f8e9d2eb3c8f4d9659cfe1d719d45dcbec139 /app
parentb284a6e07c2dd03d10eb471d69457e92bcc0ac76 (diff)
(김준회) dolce rebuild: i18n 지원
Diffstat (limited to 'app')
-rw-r--r--app/[lng]/partners/(partners)/dolce-upload/dolce-upload-page.tsx110
-rw-r--r--app/[lng]/partners/(partners)/dolce-upload/page.tsx15
2 files changed, 71 insertions, 54 deletions
diff --git a/app/[lng]/partners/(partners)/dolce-upload/dolce-upload-page.tsx b/app/[lng]/partners/(partners)/dolce-upload/dolce-upload-page.tsx
index db8d528b..43800838 100644
--- a/app/[lng]/partners/(partners)/dolce-upload/dolce-upload-page.tsx
+++ b/app/[lng]/partners/(partners)/dolce-upload/dolce-upload-page.tsx
@@ -1,6 +1,7 @@
"use client";
import { useState, useEffect, useCallback, useMemo } from "react";
+import { useParams } from "next/navigation";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Skeleton } from "@/components/ui/skeleton";
@@ -16,6 +17,7 @@ import {
} from "@/components/ui/select";
import { InfoIcon, RefreshCw, Search, Upload } from "lucide-react";
import { toast } from "sonner";
+import { useTranslation } from "@/i18n/client";
import {
UnifiedDwgReceiptItem,
fetchDwgReceiptList,
@@ -33,6 +35,10 @@ interface DolceUploadPageProps {
}
export default function DolceUploadPage({ searchParams }: DolceUploadPageProps) {
+ const params = useParams();
+ const lng = params?.lng as string;
+ const { t } = useTranslation(lng, "dolce");
+
// URL에서 초기 프로젝트 코드
const initialProjNo = (searchParams.projNo as string) || "";
@@ -78,7 +84,7 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
fetchVendorProjects(),
]);
- setVendorInfo(vendorInfoData);
+ setVendorInfo(vendorInfoData as typeof vendorInfo);
setProjects(projectsData);
// 초기 프로젝트가 있으면 도면 로드
@@ -92,12 +98,12 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
}
} catch (err) {
console.error("초기 데이터 로드 실패:", err);
- setError(err instanceof Error ? err.message : "데이터 로드 실패");
- toast.error("데이터 로드 실패");
+ setError(err instanceof Error ? err.message : t("page.initialLoadError"));
+ toast.error(t("page.initialLoadError"));
} finally {
setIsLoading(false);
}
- }, [initialProjNo]);
+ }, [initialProjNo, t]);
// 도면 목록 조회
const loadDrawings = useCallback(async () => {
@@ -114,21 +120,28 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
});
setDrawings(drawingsData);
- toast.success("도면 목록을 갱신했습니다");
+ toast.success(t("page.drawingLoadSuccess"));
} catch (err) {
console.error("도면 로드 실패:", err);
- setError(err instanceof Error ? err.message : "도면 로드 실패");
- toast.error("도면 로드 실패");
+ setError(err instanceof Error ? err.message : t("page.drawingLoadError"));
+ toast.error(t("page.drawingLoadError"));
} finally {
setIsRefreshing(false);
}
- }, [projNo, vendorInfo]);
+ }, [projNo, vendorInfo, t]);
// 초기 데이터 로드
useEffect(() => {
loadInitialData();
}, [loadInitialData]);
+ // 프로젝트 변경 시 자동 검색
+ useEffect(() => {
+ if (projNo && vendorInfo) {
+ loadDrawings();
+ }
+ }, [projNo, vendorInfo, loadDrawings]);
+
// 도면 클릭 핸들러
const handleDrawingClick = (drawing: UnifiedDwgReceiptItem) => {
setSelectedDrawing(drawing);
@@ -227,7 +240,7 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
<Alert>
<InfoIcon className="h-4 w-4" />
<AlertDescription>
- 프로젝트를 선택하여 도면 목록을 조회하세요.
+ {t("page.selectProject")}
</AlertDescription>
</Alert>
)}
@@ -235,16 +248,16 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
{/* 필터 카드 */}
<Card>
<CardHeader>
- <CardTitle>검색 필터</CardTitle>
+ <CardTitle>{t("filter.title")}</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* 프로젝트 선택 */}
<div className="space-y-2">
- <Label>프로젝트</Label>
+ <Label>{t("filter.project")}</Label>
<Select value={projNo} onValueChange={setProjNo}>
<SelectTrigger>
- <SelectValue placeholder="프로젝트를 선택하세요" />
+ <SelectValue placeholder={t("filter.projectPlaceholder")} />
</SelectTrigger>
<SelectContent>
{projects.map((project) => (
@@ -258,77 +271,69 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
{/* 도면번호 검색 */}
<div className="space-y-2">
- <Label>도면번호 (Drawing No)</Label>
+ <Label>{t("filter.drawingNo")}</Label>
<Input
value={drawingNo}
onChange={(e) => setDrawingNo(e.target.value)}
- placeholder="도면번호 입력"
+ placeholder={t("filter.drawingNoPlaceholder")}
/>
</div>
{/* 도면명 검색 */}
<div className="space-y-2">
- <Label>도면명 (Drawing Name)</Label>
+ <Label>{t("filter.drawingName")}</Label>
<Input
value={drawingName}
onChange={(e) => setDrawingName(e.target.value)}
- placeholder="도면명 입력"
+ placeholder={t("filter.drawingNamePlaceholder")}
/>
</div>
{/* 설계공종 검색 */}
<div className="space-y-2">
- <Label>설계공종 (Discipline)</Label>
+ <Label>{t("filter.discipline")}</Label>
<Input
value={discipline}
onChange={(e) => setDiscipline(e.target.value)}
- placeholder="설계공종 입력"
+ placeholder={t("filter.disciplinePlaceholder")}
/>
</div>
{/* 담당자명 검색 (클라이언트 필터) */}
<div className="space-y-2">
- <Label>담당자명 (Manager)</Label>
+ <Label>{t("filter.manager")}</Label>
<Input
value={manager}
onChange={(e) => setManager(e.target.value)}
- placeholder="담당자명 입력"
+ placeholder={t("filter.managerPlaceholder")}
/>
</div>
{/* B4(GTT) 전용: Document Type 필터 */}
{vendorInfo?.drawingKind === "B4" && (
<div className="space-y-2">
- <Label>Document Type</Label>
+ <Label>{t("filter.documentType")}</Label>
<Select value={documentType} onValueChange={(value) => setDocumentType(value as DocumentType)}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
- <SelectItem value="ALL">ALL (전체)</SelectItem>
- <SelectItem value="GTT_DELIVERABLES">GTT Deliverables (도면입수)</SelectItem>
- <SelectItem value="SHI_INPUT">SHI Input Document (도면제출)</SelectItem>
+ <SelectItem value="ALL">{t("filter.documentTypeAll")}</SelectItem>
+ <SelectItem value="GTT_DELIVERABLES">{t("filter.documentTypeGttDeliverables")}</SelectItem>
+ <SelectItem value="SHI_INPUT">{t("filter.documentTypeSHIInput")}</SelectItem>
</SelectContent>
</Select>
</div>
)}
</div>
- <div className="flex gap-2 mt-4">
+ <div className="flex gap-2 mt-4 justify-end">
<Button
onClick={handleSearch}
disabled={!projNo || isRefreshing}
- className="flex-1"
>
<Search className="h-4 w-4 mr-2" />
- 검색
- </Button>
- <Button
- variant="outline"
- onClick={handleRefresh}
- disabled={!projNo || isRefreshing}
- >
- <RefreshCw className={`h-4 w-4 ${isRefreshing ? "animate-spin" : ""}`} />
+ {t("filter.searchButton")}
</Button>
{/* B4 벤더인 경우에만 일괄 업로드 버튼 표시 */}
{vendorInfo?.drawingKind === "B4" && (
@@ -338,9 +343,16 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
disabled={!projNo || isRefreshing}
>
<Upload className="h-4 w-4 mr-2" />
- 일괄 업로드
+ {t("filter.bulkUploadButton")}
</Button>
)}
+ <Button
+ variant="outline"
+ onClick={handleRefresh}
+ disabled={!projNo || isRefreshing}
+ >
+ <RefreshCw className={`h-4 w-4 ${isRefreshing ? "animate-spin" : ""}`} />
+ </Button>
</div>
</CardContent>
</Card>
@@ -350,24 +362,20 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
<Card>
<CardHeader>
<CardTitle>
- 도면 리스트
- {filteredDrawings.length > 0 && ` (${filteredDrawings.length}건)`}
+ {t("drawingList.title")}
+ {filteredDrawings.length > 0 && ` ${t("drawingList.count", { count: filteredDrawings.length })}`}
</CardTitle>
</CardHeader>
<CardContent className="overflow-x-auto">
- {vendorInfo.drawingKind === "B4" ? (
- <DrawingListTable
- columns={createGttDrawingListColumns({ documentType })}
- data={filteredDrawings}
- onRowClick={handleDrawingClick}
- />
- ) : (
- <DrawingListTable
- columns={drawingListColumns}
- data={filteredDrawings}
- onRowClick={handleDrawingClick}
- />
- )}
+ <DrawingListTable
+ columns={
+ vendorInfo.drawingKind === "B4"
+ ? (createGttDrawingListColumns({ documentType, lng, t }) as unknown as typeof drawingListColumns)
+ : (drawingListColumns(lng, t) as unknown as typeof drawingListColumns)
+ }
+ data={filteredDrawings}
+ onRowClick={handleDrawingClick}
+ />
</CardContent>
</Card>
)}
@@ -383,6 +391,7 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
userName={vendorInfo.userName}
userEmail={vendorInfo.email}
drawingKind={vendorInfo.drawingKind}
+ lng={lng}
/>
)}
@@ -397,6 +406,7 @@ export default function DolceUploadPage({ searchParams }: DolceUploadPageProps)
userEmail={vendorInfo.email}
vendorCode={vendorInfo.vendorCode}
onUploadComplete={handleBulkUploadComplete}
+ lng={lng}
/>
)}
</div>
diff --git a/app/[lng]/partners/(partners)/dolce-upload/page.tsx b/app/[lng]/partners/(partners)/dolce-upload/page.tsx
index 97582819..4d7b1a74 100644
--- a/app/[lng]/partners/(partners)/dolce-upload/page.tsx
+++ b/app/[lng]/partners/(partners)/dolce-upload/page.tsx
@@ -31,11 +31,14 @@ function DolceUploadSkeleton() {
}
export default async function DolceUploadPageWrapper({
+ params,
searchParams,
}: {
+ params: Promise<{ lng: string }>;
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
- const params = await searchParams;
+ const { lng } = await params;
+ const resolvedParams = await searchParams;
return (
<Shell>
@@ -43,17 +46,21 @@ export default async function DolceUploadPageWrapper({
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">
- DOLCE 문서 업로드
+ {lng === "ko"
+ ? "DOLCE 도면 업로드"
+ : "DOLCE Drawing Upload"}
</h2>
<p className="text-muted-foreground">
- 설계문서를 조회하고 업로드할 수 있습니다
+ {lng === "ko"
+ ? "설계문서를 조회하고 업로드할 수 있습니다"
+ : "View and upload design documents"}
</p>
</div>
</div>
{/* 메인 컨텐츠 */}
<Suspense fallback={<DolceUploadSkeleton />}>
- <DolceUploadPage searchParams={params} />
+ <DolceUploadPage searchParams={resolvedParams} />
</Suspense>
</Shell>
);