first commit

This commit is contained in:
2026-08-17 19:45:29 +05:30
commit 3c27da77a8
510 changed files with 137749 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
import React, { useState } from "react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Card, CardContent } from "@/components/ui/card";
import { Upload, FileText, CheckCircle, X } from "lucide-react";
import { base44 } from "@/api/base44Client";
import { useToast } from "@/components/ui/use-toast";
const requiredDocuments = [
{ id: 'id', name: 'Government ID', required: true, description: 'Driver\'s license or passport' },
{ id: 'certification', name: 'Certifications', required: false, description: 'Food handler, TIPS, etc.' },
{ id: 'background_check', name: 'Background Check', required: false, description: 'If available' },
];
export default function DocumentUploadStep({ data, onNext, onBack }) {
const [documents, setDocuments] = useState(data || []);
const [uploading, setUploading] = useState({});
const { toast } = useToast();
const handleFileUpload = async (docType, file) => {
if (!file) return;
setUploading(prev => ({ ...prev, [docType]: true }));
try {
const { file_url } = await base44.integrations.Core.UploadFile({ file });
const newDoc = {
type: docType,
name: file.name,
url: file_url,
uploaded_at: new Date().toISOString(),
};
setDocuments(prev => {
const filtered = prev.filter(d => d.type !== docType);
return [...filtered, newDoc];
});
toast({
title: "✅ Document Uploaded",
description: `${file.name} uploaded successfully`,
});
} catch (error) {
toast({
title: "❌ Upload Failed",
description: error.message,
variant: "destructive",
});
} finally {
setUploading(prev => ({ ...prev, [docType]: false }));
}
};
const handleRemoveDocument = (docType) => {
setDocuments(prev => prev.filter(d => d.type !== docType));
};
const handleNext = () => {
const hasRequiredDocs = requiredDocuments
.filter(doc => doc.required)
.every(doc => documents.some(d => d.type === doc.id));
if (!hasRequiredDocs) {
toast({
title: "⚠️ Missing Required Documents",
description: "Please upload all required documents before continuing",
variant: "destructive",
});
return;
}
onNext({ type: 'documents', data: documents });
};
const getUploadedDoc = (docType) => documents.find(d => d.type === docType);
return (
<div className="space-y-6">
<div>
<h2 className="text-xl font-bold text-slate-900 mb-2">Document Upload</h2>
<p className="text-sm text-slate-500">Upload required documents for compliance</p>
</div>
<div className="space-y-4">
{requiredDocuments.map(doc => {
const uploadedDoc = getUploadedDoc(doc.id);
const isUploading = uploading[doc.id];
return (
<Card key={doc.id} className={uploadedDoc ? "border-green-500 bg-green-50" : ""}>
<CardContent className="p-4">
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<Label className="font-semibold">
{doc.name}
{doc.required && <span className="text-red-500 ml-1">*</span>}
</Label>
{uploadedDoc && (
<CheckCircle className="w-5 h-5 text-green-600" />
)}
</div>
<p className="text-sm text-slate-500">{doc.description}</p>
{uploadedDoc && (
<div className="mt-2 flex items-center gap-2">
<FileText className="w-4 h-4 text-slate-500" />
<span className="text-sm text-slate-700">{uploadedDoc.name}</span>
<button
onClick={() => handleRemoveDocument(doc.id)}
className="ml-2 text-red-500 hover:text-red-700"
>
<X className="w-4 h-4" />
</button>
</div>
)}
</div>
<div>
<label
htmlFor={`upload-${doc.id}`}
className={`cursor-pointer inline-flex items-center px-4 py-2 rounded-lg ${
uploadedDoc
? "bg-green-100 text-green-700 hover:bg-green-200"
: "bg-blue-100 text-blue-700 hover:bg-blue-200"
} transition-colors`}
>
<Upload className="w-4 h-4 mr-2" />
{isUploading ? "Uploading..." : uploadedDoc ? "Replace" : "Upload"}
</label>
<input
id={`upload-${doc.id}`}
type="file"
className="hidden"
accept=".pdf,.jpg,.jpeg,.png"
onChange={(e) => handleFileUpload(doc.id, e.target.files[0])}
disabled={isUploading}
/>
</div>
</div>
</CardContent>
</Card>
);
})}
</div>
<div className="flex justify-between pt-4">
<Button variant="outline" onClick={onBack}>
Back
</Button>
<Button onClick={handleNext} className="bg-[#0A39DF]">
Continue to Training
</Button>
</div>
</div>
);
}