Spaces:
Sleeping
Sleeping
| 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 } from "@/components/ui/card"; | |
| import { Textarea } from "@/components/ui/textarea"; | |
| import { | |
| FileUp, | |
| Loader2, | |
| Search, | |
| HelpCircle, | |
| File | |
| } from "lucide-react"; | |
| import { | |
| Tooltip, | |
| TooltipContent, | |
| TooltipProvider, | |
| TooltipTrigger, | |
| } from "@/components/ui/tooltip"; | |
| import { cn } from "@/lib/utils"; | |
| import CustomDialog from "@/components/CustomDialog"; | |
| // Interface for document types | |
| export interface DocumentType { | |
| name: string; | |
| description: string; | |
| } | |
| interface EmployeeDocumentSelectorProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| documentTypes: DocumentType[]; | |
| onSelectAndUpload: (documentType: DocumentType, file: File, description: string) => void; | |
| isUploading: boolean; | |
| } | |
| const EmployeeDocumentSelector: React.FC<EmployeeDocumentSelectorProps> = ({ | |
| isOpen, | |
| onClose, | |
| documentTypes, | |
| onSelectAndUpload, | |
| isUploading | |
| }) => { | |
| const [searchQuery, setSearchQuery] = useState(''); | |
| const [selectedType, setSelectedType] = useState<DocumentType | null>(null); | |
| const [selectedFile, setSelectedFile] = useState<File | null>(null); | |
| const [description, setDescription] = useState(''); | |
| const [step, setStep] = useState<'select-type' | 'select-file'>('select-type'); | |
| // Filter document types based on search | |
| const filteredDocTypes = documentTypes.filter(docType => | |
| docType.name.toLowerCase().includes(searchQuery.toLowerCase()) || | |
| docType.description.toLowerCase().includes(searchQuery.toLowerCase()) | |
| ); | |
| // Reset state when dialog closes | |
| const handleClose = () => { | |
| if (isUploading) return; | |
| setSelectedType(null); | |
| setSelectedFile(null); | |
| setDescription(''); | |
| setStep('select-type'); | |
| setSearchQuery(''); | |
| onClose(); | |
| }; | |
| // Handle document type selection | |
| const handleTypeSelect = (docType: DocumentType) => { | |
| setSelectedType(docType); | |
| setStep('select-file'); | |
| }; | |
| // Handle file selection | |
| const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { | |
| const files = e.target.files; | |
| if (files && files.length > 0) { | |
| setSelectedFile(files[0]); | |
| } | |
| }; | |
| // Handle description change | |
| const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | |
| setDescription(e.target.value); | |
| }; | |
| // Handle upload action | |
| const handleUpload = () => { | |
| if (selectedType && selectedFile) { | |
| onSelectAndUpload(selectedType, selectedFile, description); | |
| } | |
| }; | |
| // Go back to document type selection | |
| const handleBack = () => { | |
| setStep('select-type'); | |
| setSelectedFile(null); | |
| setDescription(''); | |
| }; | |
| return ( | |
| <CustomDialog | |
| isOpen={isOpen} | |
| onClose={handleClose} | |
| title={step === 'select-type' ? 'Select Document Type' : `Upload ${selectedType?.name}`} | |
| description={step === 'select-type' | |
| ? 'Select the type of document you want to upload' | |
| : 'Choose a file and add optional details for the selected document type'} | |
| allowClose={!isUploading} | |
| isPending={isUploading} | |
| > | |
| {step === 'select-type' ? ( | |
| <div className="space-y-4"> | |
| <div className="relative"> | |
| <Search className="absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" /> | |
| <Input | |
| placeholder="Search document types..." | |
| value={searchQuery} | |
| onChange={(e) => setSearchQuery(e.target.value)} | |
| className="pl-8" | |
| /> | |
| </div> | |
| <div className="max-h-[60vh] overflow-y-auto pr-1 space-y-1"> | |
| {filteredDocTypes.length > 0 ? ( | |
| filteredDocTypes.map((docType) => ( | |
| <TooltipProvider key={docType.name} delayDuration={300}> | |
| <Tooltip> | |
| <TooltipTrigger asChild> | |
| <Card | |
| className={cn( | |
| "p-3 cursor-pointer border hover:bg-accent transition-colors", | |
| "flex items-center justify-between" | |
| )} | |
| onClick={() => handleTypeSelect(docType)} | |
| > | |
| <span className="font-medium">{docType.name}</span> | |
| {docType.description && ( | |
| <HelpCircle className="h-4 w-4 text-muted-foreground" /> | |
| )} | |
| </Card> | |
| </TooltipTrigger> | |
| {docType.description && ( | |
| <TooltipContent side="left" className="max-w-sm"> | |
| {docType.description} | |
| </TooltipContent> | |
| )} | |
| </Tooltip> | |
| </TooltipProvider> | |
| )) | |
| ) : ( | |
| <div className="text-center py-8 text-muted-foreground"> | |
| No matching document types found | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ) : ( | |
| <div className="space-y-4"> | |
| <div className="bg-muted/50 p-3 rounded-md"> | |
| <p className="text-sm font-medium">Selected Document Type:</p> | |
| <p className="text-muted-foreground">{selectedType?.name}</p> | |
| {selectedType?.description && ( | |
| <p className="text-xs text-muted-foreground mt-1">{selectedType.description}</p> | |
| )} | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="file-upload">Select File</Label> | |
| <div className="flex items-center gap-2"> | |
| <Input | |
| id="file-upload" | |
| type="file" | |
| onChange={handleFileChange} | |
| className="flex-1" | |
| disabled={isUploading} | |
| /> | |
| </div> | |
| {selectedFile && ( | |
| <div className="flex items-center gap-2 text-sm bg-accent/50 p-2 rounded-md"> | |
| <File className="h-4 w-4" /> | |
| <span>{selectedFile.name}</span> | |
| <span className="text-muted-foreground ml-auto"> | |
| {(selectedFile.size / 1024).toFixed(1)} KB | |
| </span> | |
| </div> | |
| )} | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="document-description">Description (Optional)</Label> | |
| <Textarea | |
| id="document-description" | |
| placeholder="Add additional details about this document..." | |
| value={description} | |
| onChange={handleDescriptionChange} | |
| className="resize-none h-24" | |
| disabled={isUploading} | |
| /> | |
| <p className="text-xs text-muted-foreground"> | |
| Add any relevant information about this document such as issue date, reference numbers, etc. | |
| </p> | |
| </div> | |
| </div> | |
| )} | |
| <div className="flex justify-between pt-4 mt-4"> | |
| {step === 'select-type' ? ( | |
| <Button variant="outline" onClick={handleClose} disabled={isUploading}> | |
| Cancel | |
| </Button> | |
| ) : ( | |
| <Button variant="outline" onClick={handleBack} disabled={isUploading}> | |
| Back | |
| </Button> | |
| )} | |
| {step === 'select-file' && ( | |
| <Button | |
| onClick={handleUpload} | |
| disabled={!selectedFile || isUploading} | |
| > | |
| {isUploading ? ( | |
| <> | |
| <Loader2 className="h-4 w-4 animate-spin mr-2" /> | |
| Uploading... | |
| </> | |
| ) : ( | |
| <> | |
| <FileUp className="h-4 w-4 mr-2" /> | |
| Upload | |
| </> | |
| )} | |
| </Button> | |
| )} | |
| </div> | |
| </CustomDialog> | |
| ); | |
| }; | |
| export default EmployeeDocumentSelector; |