diff --git a/src/components/SignatureCard.tsx b/src/components/SignatureCard.tsx index 264a53e..224f426 100644 --- a/src/components/SignatureCard.tsx +++ b/src/components/SignatureCard.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; @@ -15,13 +16,16 @@ import { import { SigviewRecord as Signature } from "@/lib/pbtypes"; import { getSignatureMeta } from "@/hooks/useSignatureCategories"; import { Trash2 } from "lucide-react"; +import { SignatureEditModal } from "@/components/SignatureEditModal"; interface SignatureCardProps { signature: Signature; onDelete?: (signatureId: string) => Promise; + onUpdate?: (updatedSignature: Partial) => Promise; } -export const SignatureCard = ({ signature, onDelete }: SignatureCardProps) => { +export const SignatureCard = ({ signature, onDelete, onUpdate }: SignatureCardProps) => { + const [isEditModalOpen, setIsEditModalOpen] = useState(false); const meta = getSignatureMeta(signature.type); const isGasSite = signature.type?.toLowerCase().includes('gas'); @@ -35,79 +39,106 @@ export const SignatureCard = ({ signature, onDelete }: SignatureCardProps) => { } }; - return ( - - -
- {/* Type Badge - Most Important */} -
- - {meta.icon} - {signature.type || 'Unknown Type'} - -
- - {/* Signature Name */} -
-

- {signature.signame || 'Unnamed Signature'} -

-
- - {/* Additional Info */} -
-
- System: - {signature.system} -
-
- ID: - {signature.id} -
-
-
+ const handleUpdate = async (updatedSignature: Partial) => { + if (onUpdate) { + try { + await onUpdate(updatedSignature); + } catch (error) { + console.error('Failed to update signature:', error); + throw error; + } + } + }; - {/* Delete Button */} - {onDelete && ( -
- - - - - - - Delete Signature - - Are you sure you want to delete signature {signature.identifier}? -
- This action cannot be undone. -
-
- - - Cancel - - - Delete - - -
-
+ return ( + <> + setIsEditModalOpen(true)} + > + +
+ {/* Type Badge - Most Important */} +
+ + {meta.icon} + {signature.type || 'Unknown Type'} + +
+ + {/* Signature Name */} +
+

+ {signature.signame || 'Unnamed Signature'} +

+
+ + {/* Additional Info */} +
+
+ System: + {signature.system} +
+
+ ID: + {signature.id} +
+
- )} -
-
+ + {/* Delete Button */} + {onDelete && ( +
+ + + + + + + Delete Signature + + Are you sure you want to delete signature {signature.identifier}? +
+ This action cannot be undone. +
+
+ + + Cancel + + + Delete + + +
+
+
+ )} + + + + {/* Edit Modal */} + {onUpdate && ( + setIsEditModalOpen(false)} + onSave={handleUpdate} + /> + )} + ); }; diff --git a/src/components/SignatureCategories.tsx b/src/components/SignatureCategories.tsx index 0564ddf..1ae6ea8 100644 --- a/src/components/SignatureCategories.tsx +++ b/src/components/SignatureCategories.tsx @@ -4,14 +4,16 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/component import { ChevronDown, ChevronRight } from "lucide-react"; import { SignatureListItem } from "@/components/SignatureListItem"; import { SignatureCategory } from "@/hooks/useSignatureCategories"; +import { SigviewRecord as Signature } from "@/lib/pbtypes"; interface SignatureCategoriesProps { categories: SignatureCategory[]; onToggleCategory: (categoryId: string) => void; onDelete?: (signatureId: string) => Promise; + onUpdate?: (updatedSignature: Partial) => Promise; } -export const SignatureCategories = ({ categories, onToggleCategory, onDelete }: SignatureCategoriesProps) => { +export const SignatureCategories = ({ categories, onToggleCategory, onDelete, onUpdate }: SignatureCategoriesProps) => { if (categories.length === 0) { return ( @@ -51,7 +53,12 @@ export const SignatureCategories = ({ categories, onToggleCategory, onDelete }:
{category.signatures.map((signature) => ( - + ))}
diff --git a/src/components/SignatureEditModal.tsx b/src/components/SignatureEditModal.tsx new file mode 100644 index 0000000..fb936a8 --- /dev/null +++ b/src/components/SignatureEditModal.tsx @@ -0,0 +1,208 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; +import { Badge } from "@/components/ui/badge"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { SigviewRecord as Signature } from "@/lib/pbtypes"; +import { getSignatureMeta, getSignatureTypes } from "@/hooks/useSignatureCategories"; +import { toast } from "@/hooks/use-toast"; + +interface SignatureEditModalProps { + signature: Signature; + isOpen: boolean; + onClose: () => void; + onSave: (updatedSignature: Partial) => Promise; +} + +export const SignatureEditModal = ({ signature, isOpen, onClose, onSave }: SignatureEditModalProps) => { + const [formData, setFormData] = useState({ + type: signature.type || "unknown", + signame: signature.signame || "", + dangerous: signature.dangerous || false, + scanned: signature.scanned || "", + identifier: signature.identifier || "" + }); + const [isLoading, setIsLoading] = useState(false); + + const signatureTypes = getSignatureTypes(); + const currentMeta = getSignatureMeta(formData.type === "unknown" ? "" : formData.type); + + const handleSave = async () => { + setIsLoading(true); + try { + await onSave({ + identifier: signature.identifier, + type: formData.type === "unknown" ? undefined : formData.type, + signame: formData.signame || undefined, + dangerous: formData.dangerous, + scanned: formData.scanned || undefined + }); + onClose(); + toast({ + title: "Signature Updated", + description: "The signature has been successfully updated.", + }); + } catch (error) { + console.error('Failed to update signature:', error); + toast({ + title: "Update Failed", + description: error instanceof Error ? error.message : "Failed to update signature.", + variant: "destructive" + }); + } finally { + setIsLoading(false); + } + }; + + const handleClose = () => { + // Reset form data to original values when closing + setFormData({ + type: signature.type || "unknown", + signame: signature.signame || "", + dangerous: signature.dangerous || false, + scanned: signature.scanned || "", + identifier: signature.identifier || "" + }); + onClose(); + }; + + return ( + + + + + {currentMeta.icon} + Edit Signature + + + Modify the signature details below. All changes will be saved immediately. + + + +
+ {/* Signature Identifier (Read-only) */} +
+ + +
+ + {/* Signature Type */} +
+ + + {formData.type !== "unknown" && ( + + {currentMeta.icon} + {formData.type} + + )} +
+ + {/* Signature Name */} +
+ + setFormData(prev => ({ ...prev, signame: e.target.value }))} + placeholder="Enter signature name" + className="bg-slate-700 border-slate-600 text-slate-200" + /> +
+ + {/* Scanned Percentage */} +
+ + setFormData(prev => ({ ...prev, scanned: e.target.value }))} + placeholder="0-100" + className="bg-slate-700 border-slate-600 text-slate-200" + /> +
+ + {/* Dangerous Flag */} +
+ + setFormData(prev => ({ ...prev, dangerous: checked }))} + /> +
+ + {/* Preview */} +
+ +
+
+ + {currentMeta.icon} + {formData.type === "unknown" ? "Unknown Type" : formData.type} + + {formData.dangerous && ( + + DANGEROUS + + )} +
+
{formData.identifier}
+
{formData.signame || "Unnamed Signature"}
+ {formData.scanned && ( +
Scanned: {formData.scanned}%
+ )} +
+
+
+ + + + + +
+
+ ); +}; \ No newline at end of file diff --git a/src/components/SignatureListItem.tsx b/src/components/SignatureListItem.tsx index bb0f4da..3e6f45c 100644 --- a/src/components/SignatureListItem.tsx +++ b/src/components/SignatureListItem.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { @@ -14,13 +15,17 @@ import { import { Clock, AlertTriangle, Skull, Trash2 } from "lucide-react"; import { SigviewRecord as Signature } from "@/lib/pbtypes"; import { getSignatureMeta } from "@/hooks/useSignatureCategories"; +import { SignatureEditModal } from "@/components/SignatureEditModal"; interface SignatureListItemProps { signature: Signature; onDelete?: (signatureId: string) => Promise; + onUpdate?: (updatedSignature: Partial) => Promise; } -export const SignatureListItem = ({ signature, onDelete }: SignatureListItemProps) => { +export const SignatureListItem = ({ signature, onDelete, onUpdate }: SignatureListItemProps) => { + const [isEditModalOpen, setIsEditModalOpen] = useState(false); + const isOld = () => { if (!signature.updated) return false; const updatedTime = new Date(signature.updated); @@ -69,91 +74,116 @@ export const SignatureListItem = ({ signature, onDelete }: SignatureListItemProp } }; - return ( -
-
- {/* Type Badge - Most Important */} - - {signature.dangerous - ? - : meta.icon} - {signature.type || "Unknown Type"} - + const handleUpdate = async (updatedSignature: Partial) => { + if (onUpdate) { + try { + await onUpdate(updatedSignature); + } catch (error) { + console.error('Failed to update signature:', error); + throw error; + } + } + }; - {/* Signature Name and ID */} -
-
- {signature.identifier} -

- {signature.signame || "Unnamed Signature"} - {signature.dangerous && ( - - DANGEROUS - - )} -

+ return ( + <> +
setIsEditModalOpen(true)} + > +
+ {/* Type Badge - Most Important */} + + {signature.dangerous + ? + : meta.icon} + {signature.type || "Unknown Type"} + + + {/* Signature Name and ID */} +
+
+ {signature.identifier} +

+ {signature.signame || "Unnamed Signature"} + {signature.dangerous && ( + + DANGEROUS + + )} +

+
+
+ + {/* Dates */} +
+ {signature.updated && ( +
+ {oldEntry && } + + Updated: {formatDate(signature.updated)} +
+ )} + {signature.created && ( +
+ Created: {formatDate(signature.created)} +
+ )}
- {/* Dates */} -
- {signature.updated && ( -
- {oldEntry && } - - Updated: {formatDate(signature.updated)} -
- )} - {signature.created && ( -
- Created: {formatDate(signature.created)} -
- )} -
+ {/* Delete Button */} + {onDelete && ( + + + + + + + Delete Signature + + Are you sure you want to delete signature {signature.identifier}? +
+ This action cannot be undone. +
+
+ + + Cancel + + + Delete + + +
+
+ )}
- {/* Delete Button */} - {onDelete && ( - - - - - - - Delete Signature - - Are you sure you want to delete signature {signature.identifier}? -
- This action cannot be undone. -
-
- - - Cancel - - - Delete - - -
-
+ {/* Edit Modal */} + {onUpdate && ( + setIsEditModalOpen(false)} + onSave={handleUpdate} + /> )} -
+ ); }; diff --git a/src/components/SystemTracker.tsx b/src/components/SystemTracker.tsx index 63c8678..7175369 100644 --- a/src/components/SystemTracker.tsx +++ b/src/components/SystemTracker.tsx @@ -4,21 +4,21 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { RefreshCw, AlertCircle, Radar, Download } from "lucide-react"; import { SignatureCategories } from "@/components/SignatureCategories"; -import { SignatureCategory, useSignatureCategories } from "@/hooks/useSignatureCategories"; +import { useSignatureCategories } from "@/hooks/useSignatureCategories"; import { toast } from "@/hooks/use-toast"; import { CleanModeToggle } from "@/components/CleanModeToggle"; import pb from "@/lib/pocketbase"; import { SigviewRecord as Signature } from "@/lib/pbtypes"; -import { useEffect } from "react"; interface SystemTrackerProps { system: string; cleanMode: boolean; onCleanModeToggle: (enabled: boolean) => void; onDelete?: (signatureId: string) => Promise; + onUpdate?: (updatedSignature: Partial) => Promise; } -export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete }: SystemTrackerProps) => { +export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete, onUpdate }: SystemTrackerProps) => { const { data: signaturesData, refetch: refetchSignatures, @@ -148,6 +148,7 @@ export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete } categories={categories} onToggleCategory={toggleCategoryVisibility} onDelete={onDelete} + onUpdate={onUpdate} /> )}
diff --git a/src/hooks/useSignatureCategories.tsx b/src/hooks/useSignatureCategories.tsx index cfff434..5c98465 100644 --- a/src/hooks/useSignatureCategories.tsx +++ b/src/hooks/useSignatureCategories.tsx @@ -71,6 +71,18 @@ export const getSignatureMeta = (type: string): SignatureCategoryMeta => { return allCategories.get("unknown")!; }; +export const getSignatureTypes = (): string[] => { + return [ + "Combat", + "Homefront", + "Data", + "Relic", + "Gas", + "Ore", + "Wormhole" + ]; +}; + export const categorizeSignatures = (signatures: Map): Record => { const categories: Record = { unknown: [], diff --git a/src/pages/SystemView.tsx b/src/pages/SystemView.tsx index 36f760d..b040c66 100644 --- a/src/pages/SystemView.tsx +++ b/src/pages/SystemView.tsx @@ -89,6 +89,65 @@ export const SystemView = () => { } }; + const updateSignature = async (updatedSignature: Partial): Promise => { + try { + // Get the system ID for the current system + const systemId = await getSystemId(system); + + console.log('Updating signature:', { + identifier: updatedSignature.identifier, + systemId, + system, + updatedSignature + }); + + // Find the signature by identifier and system + const existingRecord = await pb.collection('signature').getFirstListItem( + `identifier='${updatedSignature.identifier}' && system='${systemId}'` + ); + + console.log('Found existing record:', existingRecord); + + // Prepare update data + const updateData: any = { + updated: new Date().toISOString() + }; + + if (updatedSignature.type !== undefined) { + updateData.type = updatedSignature.type; + } + if (updatedSignature.signame !== undefined) { + updateData.name = updatedSignature.signame; // Map signame to name field + } + if (updatedSignature.dangerous !== undefined) { + updateData.dangerous = updatedSignature.dangerous; + } + if (updatedSignature.scanned !== undefined) { + updateData.scanned = updatedSignature.scanned; + } + + console.log('Update data:', updateData); + + await pb.collection('signature').update(existingRecord.id, updateData); + + // Invalidate queries to refresh the data + queryClient.invalidateQueries({ queryKey: ['signatures', system] }); + + toast({ + title: "Signature Updated", + description: "The signature has been successfully updated.", + }); + } catch (error) { + console.error('Failed to update signature:', error); + toast({ + title: "Update Failed", + description: error instanceof Error ? error.message : "Failed to update signature.", + variant: "destructive" + }); + throw error; + } + }; + const handlePaste = async (e: ClipboardEvent) => { const pastedText = e.clipboardData?.getData('text'); if (!pastedText?.trim()) return; @@ -193,6 +252,7 @@ export const SystemView = () => { cleanMode={cleanMode} onCleanModeToggle={setCleanMode} onDelete={deleteSignature} + onUpdate={updateSignature} />