287 lines
9.9 KiB
TypeScript
287 lines
9.9 KiB
TypeScript
import { useState } from "react";
|
|
import { Card } from "./ui/card";
|
|
import { Button } from "./ui/button";
|
|
import { Input } from "./ui/input";
|
|
import { Label } from "./ui/label";
|
|
import { Textarea } from "./ui/textarea";
|
|
import { Badge } from "./ui/badge";
|
|
import {
|
|
FileText,
|
|
CheckCircle2,
|
|
Clock,
|
|
AlertCircle,
|
|
Plus,
|
|
Calendar
|
|
} from "lucide-react";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "./ui/dialog";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "./ui/select";
|
|
|
|
interface Document {
|
|
id: string;
|
|
title: string;
|
|
type: string;
|
|
status: "complete" | "pending" | "overdue";
|
|
dueDate: string;
|
|
lastModified: string;
|
|
}
|
|
|
|
export function EHSDocumentation() {
|
|
const [selectedDoc, setSelectedDoc] = useState<Document | null>(null);
|
|
|
|
const documents: Document[] = [
|
|
{
|
|
id: "1",
|
|
title: "Quarterly Chemical Inventory Report",
|
|
type: "Inventory Report",
|
|
status: "complete",
|
|
dueDate: "2024-12-01",
|
|
lastModified: "2024-11-20"
|
|
},
|
|
{
|
|
id: "2",
|
|
title: "Hazardous Waste Disposal Form",
|
|
type: "Waste Disposal",
|
|
status: "pending",
|
|
dueDate: "2024-11-30",
|
|
lastModified: "2024-11-22"
|
|
},
|
|
{
|
|
id: "3",
|
|
title: "Lab Safety Inspection Checklist",
|
|
type: "Inspection",
|
|
status: "overdue",
|
|
dueDate: "2024-11-15",
|
|
lastModified: "2024-10-30"
|
|
},
|
|
{
|
|
id: "4",
|
|
title: "Annual Training Documentation",
|
|
type: "Training",
|
|
status: "complete",
|
|
dueDate: "2024-09-30",
|
|
lastModified: "2024-09-28"
|
|
}
|
|
];
|
|
|
|
const getStatusBadge = (status: string) => {
|
|
switch (status) {
|
|
case "complete":
|
|
return (
|
|
<Badge className="bg-accent text-primary">
|
|
<CheckCircle2 className="w-3 h-3 mr-1" />
|
|
Complete
|
|
</Badge>
|
|
);
|
|
case "pending":
|
|
return (
|
|
<Badge className="bg-secondary text-primary">
|
|
<Clock className="w-3 h-3 mr-1" />
|
|
Pending
|
|
</Badge>
|
|
);
|
|
case "overdue":
|
|
return (
|
|
<Badge className="bg-red-100 text-red-700">
|
|
<AlertCircle className="w-3 h-3 mr-1" />
|
|
Overdue
|
|
</Badge>
|
|
);
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="p-8">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<div>
|
|
<h1 className="text-foreground mb-2">EHS Documentation</h1>
|
|
<p className="text-muted-foreground">Manage and track your Environmental Health & Safety documentation</p>
|
|
</div>
|
|
<Dialog>
|
|
<DialogTrigger asChild>
|
|
<Button className="bg-primary hover:bg-primary/90">
|
|
<Plus className="w-4 h-4 mr-2" />
|
|
New Document
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent className="max-w-2xl">
|
|
<DialogHeader>
|
|
<DialogTitle>Create EHS Document</DialogTitle>
|
|
<DialogDescription>
|
|
AI-assisted form filling using your inventory history
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="space-y-4 py-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="doc-type">Document Type</Label>
|
|
<Select>
|
|
<SelectTrigger id="doc-type">
|
|
<SelectValue placeholder="Select document type" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="inventory">Chemical Inventory Report</SelectItem>
|
|
<SelectItem value="waste">Waste Disposal Form</SelectItem>
|
|
<SelectItem value="inspection">Safety Inspection</SelectItem>
|
|
<SelectItem value="incident">Incident Report</SelectItem>
|
|
<SelectItem value="training">Training Documentation</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="doc-title">Document Title</Label>
|
|
<Input id="doc-title" placeholder="Enter document title" />
|
|
</div>
|
|
|
|
<div className="bg-accent border border-border rounded-lg p-4">
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5" />
|
|
<div>
|
|
<p className="text-foreground mb-1">AI Assistant Ready</p>
|
|
<p className="text-muted-foreground">
|
|
I can auto-fill this form using data from your inventory history, recent chemical usage, and previous documentation.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="description">Description</Label>
|
|
<Textarea
|
|
id="description"
|
|
placeholder="Describe the purpose or scope of this document..."
|
|
rows={4}
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="due-date">Due Date</Label>
|
|
<Input id="due-date" type="date" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="responsible">Responsible Person</Label>
|
|
<Input id="responsible" placeholder="Name" />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-2">
|
|
<Button className="flex-1 bg-primary hover:bg-primary/90">
|
|
Create & AI Fill
|
|
</Button>
|
|
<Button variant="outline" className="flex-1">
|
|
Create Empty
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
|
|
{/* Summary Cards */}
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8">
|
|
<Card className="p-6">
|
|
<p className="text-muted-foreground mb-1">Total Documents</p>
|
|
<p className="text-foreground">{documents.length}</p>
|
|
</Card>
|
|
<Card className="p-6">
|
|
<p className="text-muted-foreground mb-1">Complete</p>
|
|
<p className="text-primary">
|
|
{documents.filter(d => d.status === "complete").length}
|
|
</p>
|
|
</Card>
|
|
<Card className="p-6">
|
|
<p className="text-muted-foreground mb-1">Pending</p>
|
|
<p className="text-[#7ab5a0]">
|
|
{documents.filter(d => d.status === "pending").length}
|
|
</p>
|
|
</Card>
|
|
<Card className="p-6">
|
|
<p className="text-muted-foreground mb-1">Overdue</p>
|
|
<p className="text-red-600">
|
|
{documents.filter(d => d.status === "overdue").length}
|
|
</p>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Documents List */}
|
|
<div className="space-y-4">
|
|
{documents.map((doc) => (
|
|
<Card
|
|
key={doc.id}
|
|
className="p-6 hover:shadow-md transition-shadow cursor-pointer"
|
|
onClick={() => setSelectedDoc(doc)}
|
|
>
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex items-start gap-4 flex-1">
|
|
<div className="p-3 bg-muted rounded-lg">
|
|
<FileText className="w-6 h-6 text-primary" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<div className="flex items-center gap-3 mb-2">
|
|
<h3 className="text-foreground">{doc.title}</h3>
|
|
{getStatusBadge(doc.status)}
|
|
</div>
|
|
<p className="text-muted-foreground mb-3">{doc.type}</p>
|
|
<div className="flex items-center gap-6 text-muted-foreground">
|
|
<div className="flex items-center gap-2">
|
|
<Calendar className="w-4 h-4" />
|
|
<span>Due: {doc.dueDate}</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Clock className="w-4 h-4" />
|
|
<span>Modified: {doc.lastModified}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Button variant="outline">View</Button>
|
|
</div>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
|
|
{/* AI Features Info */}
|
|
<Card className="p-6 mt-8 bg-gradient-to-r from-accent to-secondary border-border">
|
|
<div className="flex items-start gap-4">
|
|
<div className="p-3 bg-card rounded-lg">
|
|
<CheckCircle2 className="w-6 h-6 text-primary" />
|
|
</div>
|
|
<div>
|
|
<h3 className="text-foreground mb-2">AI-Powered Documentation</h3>
|
|
<p className="text-muted-foreground mb-3">
|
|
Labwise uses your inventory history and chemical usage data to automatically fill out EHS forms, saving you hours of tedious paperwork.
|
|
</p>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div>
|
|
<p className="text-primary">✓ Auto-fill from inventory</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-primary">✓ Suggest compliance requirements</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-primary">✓ Track submission deadlines</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |