1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
// lib/vendor-document-list/plant/upload/components/history-dialog.tsx
"use client"
import * as React from "react"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Badge } from "@/components/ui/badge"
import { ScrollArea } from "@/components/ui/scroll-area"
import {
CheckCircle2,
XCircle,
Clock,
FileText,
User,
Calendar,
AlertCircle
} from "lucide-react"
import { StageSubmissionView } from "@/db/schema"
import { formatDateTime } from "@/lib/utils"
interface HistoryDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
submission: StageSubmissionView
}
export function HistoryDialog({
open,
onOpenChange,
submission
}: HistoryDialogProps) {
const history = submission.submissionHistory || []
const getStatusIcon = (status: string, reviewStatus?: string) => {
if (reviewStatus === "APPROVED") {
return <CheckCircle2 className="h-4 w-4 text-success" />
}
if (reviewStatus === "REJECTED") {
return <XCircle className="h-4 w-4 text-destructive" />
}
if (status === "SUBMITTED") {
return <Clock className="h-4 w-4 text-primary" />
}
return <AlertCircle className="h-4 w-4 text-muted-foreground" />
}
const getStatusBadge = (status: string, reviewStatus?: string) => {
const variant = reviewStatus === "APPROVED" ? "success" :
reviewStatus === "REJECTED" ? "destructive" :
status === "SUBMITTED" ? "default" : "secondary"
return (
<Badge variant={variant}>
{reviewStatus || status}
</Badge>
)
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl max-h-[80vh]">
<DialogHeader>
<DialogTitle>Submission History</DialogTitle>
<DialogDescription>
View all submission history for this stage
</DialogDescription>
</DialogHeader>
{/* Document Info */}
<div className="grid gap-2 p-4 bg-muted rounded-lg">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<FileText className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium">{submission.docNumber}</span>
<span className="text-sm text-muted-foreground">
- {submission.documentTitle}
</span>
</div>
<Badge variant="outline">{submission.stageName}</Badge>
</div>
</div>
{/* History Timeline */}
<ScrollArea className="h-[400px] pr-4">
{history.length === 0 ? (
<div className="text-center py-8 text-muted-foreground">
No submission history available
</div>
) : (
<div className="space-y-4">
{history.map((item, index) => (
<div key={item.submissionId} className="relative">
{/* Timeline line */}
{index < history.length - 1 && (
<div className="absolute left-5 top-10 bottom-0 w-0.5 bg-border" />
)}
{/* Timeline item */}
<div className="flex gap-4">
<div className="flex-shrink-0 w-10 h-10 rounded-full bg-background border-2 border-border flex items-center justify-center">
{getStatusIcon(item.status, item.reviewStatus)}
</div>
<div className="flex-1 pb-4">
<div className="flex items-center gap-2 mb-2">
<span className="font-medium">Revision {item.revisionNumber}</span>
{getStatusBadge(item.status, item.reviewStatus)}
{item.syncStatus && (
<Badge variant="outline" className="text-xs">
Sync: {item.syncStatus}
</Badge>
)}
</div>
<div className="grid gap-1 text-sm text-muted-foreground">
<div className="flex items-center gap-2">
<User className="h-3 w-3" />
<span>{item.submittedBy}</span>
</div>
<div className="flex items-center gap-2">
<Calendar className="h-3 w-3" />
<span>{formatDateTime(new Date(item.submittedAt))}</span>
</div>
<div className="flex items-center gap-2">
<FileText className="h-3 w-3" />
<span>{item.fileCount} file(s)</span>
</div>
</div>
</div>
</div>
</div>
))}
</div>
)}
</ScrollArea>
</DialogContent>
</Dialog>
)
}
|