Load in improvements
CI / build (push) Has been skipped
CI / deploy (push) Successful in 1m4s

This commit is contained in:
2026-03-18 18:51:26 -05:00
parent f9a19eb4c4
commit f2dcff7b71
3 changed files with 48 additions and 33 deletions
+10 -1
View File
@@ -2,6 +2,7 @@ import type { Component } from 'solid-js';
import { A, useLocation, useNavigate } from '@solidjs/router'; import { A, useLocation, useNavigate } from '@solidjs/router';
import { Show } from 'solid-js'; import { Show } from 'solid-js';
import { authStore } from './store/authStore'; import { authStore } from './store/authStore';
import { appStore } from './store/appStore';
interface AppContainerProps { interface AppContainerProps {
children?: any; children?: any;
@@ -25,7 +26,15 @@ const AppContainer: Component<AppContainerProps> = (props) => {
<div class="flex justify-between h-16"> <div class="flex justify-between h-16">
<div class="flex items-center gap-8"> <div class="flex items-center gap-8">
<div class="flex-shrink-0 flex items-center"> <div class="flex-shrink-0 flex items-center">
<span class="font-bold text-xl text-gray-900 tracking-tight">EstiMaker</span> <button
onClick={() => {
appStore.resetEstimate();
navigate('/');
}}
class="font-bold text-xl text-gray-900 tracking-tight hover:text-blue-600 transition-colors"
>
EstiMaker
</button>
</div> </div>
<nav class="flex space-x-4"> <nav class="flex space-x-4">
<A <A
+1 -1
View File
@@ -64,7 +64,7 @@ const ItemExtractor: Component<ItemExtractorProps> = () => {
<Show when={mode() === 'initial'}> <Show when={mode() === 'initial'}>
<div class="flex flex-col items-center justify-center space-y-8 py-12"> <div class="flex flex-col items-center justify-center space-y-8 py-12">
<div class="text-center mb-4"> <div class="text-center mb-4">
<h1 class="text-4xl font-black text-gray-900 mb-3 tracking-tight lowercase">EstiMaker</h1> <h1 class="text-4xl font-black text-gray-900 mb-3 tracking-tight">EstiMaker</h1>
<p class="text-gray-500 text-lg">Start a new project or continue where you left off.</p> <p class="text-gray-500 text-lg">Start a new project or continue where you left off.</p>
</div> </div>
+37 -31
View File
@@ -1,7 +1,7 @@
import type { Component } from 'solid-js'; import type { Component } from 'solid-js';
import { createSignal, Show, For, createEffect } from 'solid-js'; import { createSignal, Show, For, createEffect } from 'solid-js';
import { Portal } from 'solid-js/web'; import { Portal } from 'solid-js/web';
import { X, User } from 'lucide-solid'; import { X } from 'lucide-solid';
import { pb, COLLECTIONS } from '../utils/db'; import { pb, COLLECTIONS } from '../utils/db';
import { appStore } from '../store/appStore'; import { appStore } from '../store/appStore';
import { normalizeScopes } from '../utils/scope-utils'; import { normalizeScopes } from '../utils/scope-utils';
@@ -14,6 +14,7 @@ interface CloudLoadModalProps {
const CloudLoadModal: Component<CloudLoadModalProps> = (props) => { const CloudLoadModal: Component<CloudLoadModalProps> = (props) => {
const [cloudEstimates, setCloudEstimates] = createSignal<any[]>([]); const [cloudEstimates, setCloudEstimates] = createSignal<any[]>([]);
const [isCloudLoading, setIsCloudLoading] = createSignal(false); const [isCloudLoading, setIsCloudLoading] = createSignal(false);
const [loadingRecordId, setLoadingRecordId] = createSignal<string | null>(null);
createEffect(() => { createEffect(() => {
if (props.show) { if (props.show) {
@@ -24,8 +25,10 @@ const CloudLoadModal: Component<CloudLoadModalProps> = (props) => {
const loadCloudEstimatesList = async () => { const loadCloudEstimatesList = async () => {
setIsCloudLoading(true); setIsCloudLoading(true);
try { try {
// Optimized: Only fetch metadata fields to keep the list response small and fast
const records = await pb.collection(COLLECTIONS.ESTIMATES).getFullList({ const records = await pb.collection(COLLECTIONS.ESTIMATES).getFullList({
sort: '-created' sort: '-created',
fields: 'id,name,created,updated'
}); });
setCloudEstimates(records); setCloudEstimates(records);
} catch (err) { } catch (err) {
@@ -36,28 +39,36 @@ const CloudLoadModal: Component<CloudLoadModalProps> = (props) => {
} }
}; };
const loadFromCloud = (record: any) => { const loadFromCloud = async (recordMetadata: any) => {
const data = record.items; // items holds the full JSON blob setLoadingRecordId(recordMetadata.id);
if (!data) return; try {
// Fetch the full record with all fields (items, history) only when requested
const record = await pb.collection(COLLECTIONS.ESTIMATES).getOne(recordMetadata.id);
const data = record.items;
if (!data) return;
if (data.scopes) appStore.setScopes(normalizeScopes(data.scopes)); if (data.scopes) appStore.setScopes(normalizeScopes(data.scopes));
if (data.subScopes) appStore.setSubScopes(data.subScopes); if (data.subScopes) appStore.setSubScopes(data.subScopes);
if (data.items) appStore.setEstimateItems(data.items); if (data.items) appStore.setEstimateItems(data.items);
if (data.clientInfo) appStore.setClientInfo(data.clientInfo); if (data.clientInfo) appStore.setClientInfo(data.clientInfo);
if (data.jobInfo) appStore.setJobInfo(data.jobInfo); if (data.jobInfo) appStore.setJobInfo(data.jobInfo);
if (data.generalEstimateNotes !== undefined) appStore.setGeneralEstimateNotes(data.generalEstimateNotes); if (data.generalEstimateNotes !== undefined) appStore.setGeneralEstimateNotes(data.generalEstimateNotes);
if (data.generalPreNotes !== undefined) appStore.setGeneralPreNotes(data.generalPreNotes); if (data.generalPreNotes !== undefined) appStore.setGeneralPreNotes(data.generalPreNotes);
appStore.setEstimateName(record.name); appStore.setEstimateName(record.name);
appStore.setEstimateId(record.id); appStore.setEstimateId(record.id);
appStore.setHistory(record.history || []); appStore.setHistory(record.history || []);
appStore.setLatestSnapshot(record.items); appStore.setLatestSnapshot(record.items);
appStore.setIsLatestVersion(true); appStore.setIsLatestVersion(true);
// Also clear out the extracted CSV items so we don't accidentally switch back to the upload screen or cause conflicts appStore.setItems([]);
appStore.setItems([]); props.onClose();
} catch (err) {
props.onClose(); console.error(err);
alert('Failed to load full estimate data.');
} finally {
setLoadingRecordId(null);
}
}; };
return ( return (
@@ -85,18 +96,13 @@ const CloudLoadModal: Component<CloudLoadModalProps> = (props) => {
<p class="text-[10px] text-muted-foreground font-medium uppercase tracking-wider"> <p class="text-[10px] text-muted-foreground font-medium uppercase tracking-wider">
{new Date(record.created).toLocaleDateString()} {new Date(record.created).toLocaleDateString()}
</p> </p>
<Show when={record.items?.savedBy}>
<div class="flex items-center gap-1.5 mt-1.5 grayscale opacity-70">
<User class="w-3 h-3 text-muted-foreground" />
<span class="text-[10px] font-bold text-muted-foreground uppercase tracking-tight">{record.items.savedBy}</span>
</div>
</Show>
</div> </div>
<button <button
disabled={loadingRecordId() !== null}
onClick={() => loadFromCloud(record)} 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" 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 disabled:opacity-50"
> >
Load {loadingRecordId() === record.id ? 'Fetching...' : 'Load'}
</button> </button>
</div> </div>
)} )}