Full Pocketbase Integration
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import type { Component } from 'solid-js';
|
||||
import { createSignal, Show, For, createEffect } from 'solid-js';
|
||||
import { Portal } from 'solid-js/web';
|
||||
import { X } from 'lucide-solid';
|
||||
import { pb, COLLECTIONS } from '../utils/db';
|
||||
import { appStore } from '../store/appStore';
|
||||
|
||||
interface CloudLoadModalProps {
|
||||
show: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const CloudLoadModal: Component<CloudLoadModalProps> = (props) => {
|
||||
const [cloudEstimates, setCloudEstimates] = createSignal<any[]>([]);
|
||||
const [isCloudLoading, setIsCloudLoading] = createSignal(false);
|
||||
|
||||
createEffect(() => {
|
||||
if (props.show) {
|
||||
loadCloudEstimatesList();
|
||||
}
|
||||
});
|
||||
|
||||
const loadCloudEstimatesList = async () => {
|
||||
setIsCloudLoading(true);
|
||||
try {
|
||||
const records = await pb.collection(COLLECTIONS.ESTIMATES).getFullList({
|
||||
sort: '-created'
|
||||
});
|
||||
setCloudEstimates(records);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert('Failed to list estimates.');
|
||||
} finally {
|
||||
setIsCloudLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const loadFromCloud = (record: any) => {
|
||||
const data = record.items; // items holds the full JSON blob
|
||||
if (!data) return;
|
||||
|
||||
if (data.scopes) appStore.setScopes(data.scopes);
|
||||
if (data.subScopes) appStore.setSubScopes(data.subScopes);
|
||||
if (data.items) appStore.setEstimateItems(data.items);
|
||||
if (data.clientInfo) appStore.setClientInfo(data.clientInfo);
|
||||
if (data.jobInfo) appStore.setJobInfo(data.jobInfo);
|
||||
if (data.generalEstimateNotes !== undefined) appStore.setGeneralEstimateNotes(data.generalEstimateNotes);
|
||||
if (data.generalPreNotes !== undefined) appStore.setGeneralPreNotes(data.generalPreNotes);
|
||||
|
||||
appStore.setEstimateName(record.name);
|
||||
appStore.setEstimateId(record.id);
|
||||
|
||||
// Also clear out the extracted CSV items so we don't accidentally switch back to the upload screen or cause conflicts
|
||||
appStore.setItems([]);
|
||||
|
||||
props.onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Show when={props.show}>
|
||||
<Portal>
|
||||
<div class="fixed inset-0 z-[100] flex flex-col items-center justify-center bg-background/80 backdrop-blur-sm p-4 animate-in fade-in duration-200">
|
||||
<div class="bg-card w-full max-w-2xl max-h-[85vh] flex flex-col rounded-3xl shadow-premium border border-border overflow-hidden animate-in zoom-in-95 duration-200">
|
||||
<div class="flex items-center justify-between p-6 border-b border-border">
|
||||
<h3 class="text-xl font-black">Load from Cloud</h3>
|
||||
<button onClick={props.onClose} class="p-2 hover:bg-muted rounded-xl transition-colors">
|
||||
<X class="w-5 h-5 text-muted-foreground" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-4 flex flex-col">
|
||||
<Show
|
||||
when={!isCloudLoading()}
|
||||
fallback={<div class="py-12 text-center text-muted-foreground">Loading estimates...</div>}
|
||||
>
|
||||
<div class="space-y-3">
|
||||
<For each={cloudEstimates()}>
|
||||
{(record) => (
|
||||
<div class="group flex items-center justify-between p-4 rounded-2xl border border-border/60 bg-muted/10 hover:bg-primary/5 hover:border-primary/30 transition-all">
|
||||
<div>
|
||||
<h4 class="font-bold text-foreground mb-1">{record.name}</h4>
|
||||
<p class="text-[10px] text-muted-foreground font-medium uppercase tracking-wider">
|
||||
{new Date(record.created).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => loadFromCloud(record)}
|
||||
class="px-4 py-2 bg-background border border-border rounded-xl text-xs font-bold shadow-sm hover:text-primary hover:border-primary/50 transition-all opacity-0 group-hover:opacity-100"
|
||||
>
|
||||
Load
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
<Show when={cloudEstimates().length === 0}>
|
||||
<div class="py-12 text-center text-muted-foreground/60 border-2 border-dashed border-border/60 rounded-xl bg-muted/5">
|
||||
No saved estimates found.
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Portal>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
|
||||
export default CloudLoadModal;
|
||||
Reference in New Issue
Block a user