diff --git a/src/routes/(app)/properties/+page.server.ts b/src/routes/(app)/properties/+page.server.ts index 14e41cb..2438ec5 100644 --- a/src/routes/(app)/properties/+page.server.ts +++ b/src/routes/(app)/properties/+page.server.ts @@ -1,9 +1,53 @@ import { error } from '@sveltejs/kit'; import { listProperties } from '$lib/server/services/properties'; +import type { Property } from '$lib/server/db/schema/properties'; import type { PageServerLoad } from './$types'; +export type PropertyRow = Property & { depth: number }; + +/** + * Reorder the flat company-scoped property list into a depth-first traversal + * so parents render immediately above their children. Within each level we + * sort by name. Orphan rows (parent_id points outside the visible set — + * shouldn't happen with the current restrict-on-delete policy, but defended + * here so the UI never silently drops a row) are appended at the end as roots. + */ +function flattenTree(rows: Property[]): PropertyRow[] { + const byParent = new Map(); + for (const r of rows) { + const key = r.parentId; + const list = byParent.get(key); + if (list) list.push(r); + else byParent.set(key, [r]); + } + for (const list of byParent.values()) { + list.sort((a, b) => a.name.localeCompare(b.name)); + } + + const out: PropertyRow[] = []; + const visible = new Set(rows.map((r) => r.id)); + function walk(parentId: string | null, depth: number): void { + const list = byParent.get(parentId) ?? []; + for (const r of list) { + out.push({ ...r, depth }); + walk(r.id, depth + 1); + } + } + walk(null, 0); + + if (out.length < rows.length) { + const seen = new Set(out.map((r) => r.id)); + for (const r of rows) { + if (!seen.has(r.id) && (!r.parentId || !visible.has(r.parentId))) { + out.push({ ...r, depth: 0 }); + } + } + } + return out; +} + export const load: PageServerLoad = async ({ locals }) => { if (!locals.company) throw error(400, 'No active company. Pick one from the sidebar.'); - const rows = await listProperties(locals.company.id); - return { properties: rows }; + const flat = await listProperties(locals.company.id); + return { properties: flattenTree(flat) }; }; diff --git a/src/routes/(app)/properties/+page.svelte b/src/routes/(app)/properties/+page.svelte index 9e4c1ba..85acd4e 100644 --- a/src/routes/(app)/properties/+page.svelte +++ b/src/routes/(app)/properties/+page.svelte @@ -42,7 +42,9 @@ {#each data.properties as p} - + + {#if p.depth > 0}{/if} {p.name} {p.kind ?? '—'}