260322:1648 Correct Coresspondence / Doing RFA / Correct CI
CI Pipeline / build (push) Failing after 12m41s
Build and Deploy / deploy (push) Failing after 2m44s

This commit is contained in:
admin
2026-03-22 16:48:12 +07:00
parent e5deedb42e
commit 11984bfa29
683 changed files with 105251 additions and 29068 deletions
+56 -59
View File
@@ -1,34 +1,34 @@
"use client";
'use client';
import type { RFA, RFAItem } from "@/types/rfa";
import { StatusBadge } from "@/components/common/status-badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { format } from "date-fns";
import { ArrowLeft, CheckCircle, XCircle, Loader2 } from "lucide-react";
import Link from "next/link";
import { useState } from "react";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { useProcessRFA } from "@/hooks/use-rfa";
import type { RFA, RFAItem } from '@/types/rfa';
import { StatusBadge } from '@/components/common/status-badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { format } from 'date-fns';
import { ArrowLeft, CheckCircle, XCircle, Loader2 } from 'lucide-react';
import Link from 'next/link';
import { useState } from 'react';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { useProcessRFA } from '@/hooks/use-rfa';
interface RFADetailProps {
data: RFA;
}
export function RFADetail({ data }: RFADetailProps) {
const [actionState, setActionState] = useState<"approve" | "reject" | null>(null);
const [comments, setComments] = useState("");
const [actionState, setActionState] = useState<'approve' | 'reject' | null>(null);
const [comments, setComments] = useState('');
const processMutation = useProcessRFA();
const currentRevision = data.revisions.find((revision) => revision.isCurrent) ?? data.revisions[0];
const currentItems = currentRevision?.items ?? [];
const currentStatus = currentRevision?.statusCode?.statusName || currentRevision?.statusCode?.statusCode || "Unknown";
const currentStatus = currentRevision?.statusCode?.statusName || currentRevision?.statusCode?.statusCode || 'Unknown';
const createdAt = data.correspondence?.createdAt || currentRevision?.createdAt;
const getDrawingNumber = (item: RFAItem) =>
item.shopDrawingRevision?.shopDrawing?.drawingNumber ||
item.asBuiltDrawingRevision?.asBuiltDrawing?.drawingNumber ||
"-";
'-';
const getRevisionLabel = (item: RFAItem) => {
if (item.shopDrawingRevision?.revisionLabel) {
@@ -47,16 +47,16 @@ export function RFADetail({ data }: RFADetailProps) {
return String(item.asBuiltDrawingRevision.revisionNumber);
}
return "-";
return '-';
};
const getRevisionTitle = (item: RFAItem) =>
item.shopDrawingRevision?.title || item.asBuiltDrawingRevision?.title || "-";
item.shopDrawingRevision?.title || item.asBuiltDrawingRevision?.title || '-';
const handleProcess = () => {
if (!actionState) return;
const apiAction = actionState === "approve" ? "APPROVE" : "REJECT";
const apiAction = actionState === 'approve' ? 'APPROVE' : 'REJECT';
processMutation.mutate(
{
@@ -69,7 +69,7 @@ export function RFADetail({ data }: RFADetailProps) {
{
onSuccess: () => {
setActionState(null);
setComments("");
setComments('');
// Query invalidation handled in hook
},
}
@@ -87,29 +87,24 @@ export function RFADetail({ data }: RFADetailProps) {
</Button>
</Link>
<div>
<h1 className="text-2xl font-bold">{data.correspondence?.correspondenceNumber || "RFA"}</h1>
<h1 className="text-2xl font-bold">{data.correspondence?.correspondenceNumber || 'RFA'}</h1>
{createdAt && (
<p className="text-muted-foreground">
Created on {format(new Date(createdAt), "dd MMM yyyy HH:mm")}
</p>
<p className="text-muted-foreground">Created on {format(new Date(createdAt), 'dd MMM yyyy HH:mm')}</p>
)}
</div>
</div>
{currentStatus === "PENDING" && (
{currentStatus === 'PENDING' && (
<div className="flex gap-2">
<Button
variant="outline"
className="text-destructive hover:text-destructive hover:bg-destructive/10"
onClick={() => setActionState("reject")}
onClick={() => setActionState('reject')}
>
<XCircle className="mr-2 h-4 w-4" />
Reject
</Button>
<Button
className="bg-green-600 hover:bg-green-700 text-white"
onClick={() => setActionState("approve")}
>
<Button className="bg-green-600 hover:bg-green-700 text-white" onClick={() => setActionState('approve')}>
<CheckCircle className="mr-2 h-4 w-4" />
Approve
</Button>
@@ -117,35 +112,37 @@ export function RFADetail({ data }: RFADetailProps) {
)}
</div>
{/* Action Input Area */}
{actionState && (
{/* Action Input Area */}
{actionState && (
<Card className="border-primary">
<CardHeader>
<CardTitle className="text-lg">
{actionState === "approve" ? "Confirm Approval" : "Confirm Rejection"}
</CardTitle>
<CardTitle className="text-lg">
{actionState === 'approve' ? 'Confirm Approval' : 'Confirm Rejection'}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label>Comments</Label>
<Textarea
value={comments}
onChange={(e) => setComments(e.target.value)}
placeholder="Enter comments..."
/>
</div>
<div className="flex justify-end gap-2">
<Button variant="ghost" onClick={() => setActionState(null)}>Cancel</Button>
<Button
variant={actionState === "approve" ? "default" : "destructive"}
onClick={handleProcess}
disabled={processMutation.isPending}
className={actionState === "approve" ? "bg-green-600 hover:bg-green-700" : ""}
>
{processMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Confirm {actionState === "approve" ? "Approve" : "Reject"}
</Button>
</div>
<div className="space-y-2">
<Label>Comments</Label>
<Textarea
value={comments}
onChange={(e) => setComments(e.target.value)}
placeholder="Enter comments..."
/>
</div>
<div className="flex justify-end gap-2">
<Button variant="ghost" onClick={() => setActionState(null)}>
Cancel
</Button>
<Button
variant={actionState === 'approve' ? 'default' : 'destructive'}
onClick={handleProcess}
disabled={processMutation.isPending}
className={actionState === 'approve' ? 'bg-green-600 hover:bg-green-700' : ''}
>
{processMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Confirm {actionState === 'approve' ? 'Approve' : 'Reject'}
</Button>
</div>
</CardContent>
</Card>
)}
@@ -156,7 +153,7 @@ export function RFADetail({ data }: RFADetailProps) {
<Card>
<CardHeader>
<div className="flex justify-between items-start">
<CardTitle className="text-xl">{currentRevision?.subject || "Untitled RFA"}</CardTitle>
<CardTitle className="text-xl">{currentRevision?.subject || 'Untitled RFA'}</CardTitle>
<StatusBadge status={currentStatus} />
</div>
</CardHeader>
@@ -164,7 +161,7 @@ export function RFADetail({ data }: RFADetailProps) {
<div>
<h3 className="font-semibold mb-2">Description</h3>
<p className="text-gray-700 whitespace-pre-wrap">
{currentRevision?.description || "No description provided."}
{currentRevision?.description || 'No description provided.'}
</p>
</div>
@@ -212,14 +209,14 @@ export function RFADetail({ data }: RFADetailProps) {
<CardContent className="space-y-4">
<div>
<p className="text-sm font-medium text-muted-foreground">Project</p>
<p className="font-medium mt-1">{data.correspondence?.project?.projectName || "-"}</p>
<p className="font-medium mt-1">{data.correspondence?.project?.projectName || '-'}</p>
</div>
<hr className="my-4 border-t" />
<div>
<p className="text-sm font-medium text-muted-foreground">Discipline</p>
<p className="font-medium mt-1">{data.discipline?.name || data.discipline?.code || "-"}</p>
<p className="font-medium mt-1">{data.discipline?.name || data.discipline?.code || '-'}</p>
</div>
</CardContent>
</Card>