import { createSignal, createResource, Show, For, onMount } from "solid-js"; import { pb } from "@/lib/pocketbase"; import { store, activeNoteId } from "@/store"; import { Search, File as FileIcon, Loader2, FolderOpen } from "lucide-solid"; interface JobFileSelectorProps { onSelectFile: (jobId: string, filename: string) => void; } export const JobFileSelector = (props: JobFileSelectorProps) => { const [query, setQuery] = createSignal(""); const [selectedJobId, setSelectedJobId] = createSignal(null); // Auto-detect job ID from active note tags (traversing up hierarchy) onMount(() => { const currentNoteId = activeNoteId(); if (currentNoteId) { let currentId = currentNoteId; let currentNote = store.notes.find(n => n.id === currentId); let depth = 0; // Traverse up "child-of-" tags to find the root or any ancestor with a job_id while (currentNote && depth < 10) { const jobIdTag = currentNote.tags?.find(t => t.startsWith("job_id:")); if (jobIdTag) { const id = jobIdTag.split(":")[1]; if (id) { setSelectedJobId(id); return; // Found it! } } const parentTag = currentNote.tags?.find(t => t.startsWith("child-of-")); if (!parentTag) break; const parentId = parentTag.replace("child-of-", ""); const parent = store.notes.find(n => n.id === parentId); if (!parent) break; currentNote = parent; depth++; } } }); // Query Jobs const [jobs] = createResource(query, async (q) => { if (!q.trim()) return []; try { const res = await pb.collection('Job_Info_Prod').getList(1, 10, { filter: `Job_Number ~ "${q}" || Job_Name ~ "${q}"`, sort: '-created', requestKey: null // Allow concurrent overlapping requests without auto-cancelling if needed, or leave it }); return res.items; } catch (e) { return []; } }); // Fetch details for the selected job to list files const [selectedJob] = createResource(selectedJobId, async (id) => { if (!id) return null; try { const data = await pb.collection('Job_Info_Prod').getOne(id); console.log("Job File Selector Selected Job Data:", data); return data; } catch (e) { console.error("Job File Selector Error Fetching Job:", e); return null; } }); const categories = ["plans", "EST_and_CO", "Addendums", "files"] as const; return (

Embed a Job File

Search for a Prism job to browse its files.

setQuery(e.currentTarget.value)} />
0}>
{(job) => ( )}
Loading Job Files...
{(jobRecord) => (

{jobRecord().Job_Name || "Unnamed Job"}

Job #{jobRecord().Job_Number || jobRecord().id}
{(category) => { let files = jobRecord()[category]; if (files === null || files === undefined || files === "") return null; if (!Array.isArray(files)) files = [files]; files = files.filter(Boolean); if (files.length === 0) return null; return (

{category.replace(/_/g, " ")}

{(filename) => ( )}
); }}
{/* Empty state if no files at all */} { const val = jobRecord()[c]; return !val || (Array.isArray(val) && val.length === 0) || (typeof val === 'string' && val.trim() === ''); })}>
No files found for this job.
)}
); };