perf: memoize parseImageIds, fix checkLimit OR query, loading skeletons, dashboard cache, compound indexes, sidebar active state, matches notified fix, padding fixes, match criteria in property detail
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
TABLES,
|
||||
type Property,
|
||||
type PropertyMatch,
|
||||
type CustomerSearch,
|
||||
type Activity,
|
||||
} from "@/lib/appwrite/schema";
|
||||
import { createAdminClient } from "@/lib/appwrite/server";
|
||||
@@ -35,7 +36,7 @@ export default async function PropertyDetailPage({ params }: Props) {
|
||||
|
||||
if (property.tenantId !== ctx.tenantId) notFound();
|
||||
|
||||
const [customers, matchesResult, activitiesResult] = await Promise.all([
|
||||
const [customers, matchesResult, activitiesResult, searchesResult] = await Promise.all([
|
||||
listCustomers(ctx.tenantId),
|
||||
tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
@@ -57,11 +58,19 @@ export default async function PropertyDetailPage({ params }: Props) {
|
||||
Query.limit(20),
|
||||
],
|
||||
}),
|
||||
tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
tableId: TABLES.customerSearches,
|
||||
queries: [
|
||||
Query.equal("tenantId", ctx.tenantId),
|
||||
Query.limit(200),
|
||||
],
|
||||
}),
|
||||
]);
|
||||
|
||||
const matches = JSON.parse(JSON.stringify(matchesResult.rows)) as PropertyMatch[];
|
||||
const activities = JSON.parse(JSON.stringify(activitiesResult.rows)) as Activity[];
|
||||
const customerMap = Object.fromEntries(customers.map((c) => [c.$id, c.name]));
|
||||
const searches = JSON.parse(JSON.stringify(searchesResult.rows)) as CustomerSearch[];
|
||||
const imageIds = parseImageIds(property.imageIds);
|
||||
|
||||
return (
|
||||
@@ -70,7 +79,8 @@ export default async function PropertyDetailPage({ params }: Props) {
|
||||
matches={matches}
|
||||
activities={activities}
|
||||
imageIds={imageIds}
|
||||
customerMap={customerMap}
|
||||
customers={customers}
|
||||
searches={searches}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
||||
export default function PropertiesLoading() {
|
||||
return (
|
||||
<div className="flex flex-1 flex-col gap-4 p-4 md:p-6">
|
||||
{/* Başlık + buton */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<Skeleton className="h-7 w-24" />
|
||||
<Skeleton className="h-4 w-40" />
|
||||
</div>
|
||||
<Skeleton className="h-9 w-28 rounded-md" />
|
||||
</div>
|
||||
|
||||
{/* Filtre bar */}
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Skeleton className="h-9 w-48 rounded-md" />
|
||||
<Skeleton className="h-9 w-32 rounded-md" />
|
||||
<Skeleton className="h-9 w-32 rounded-md" />
|
||||
</div>
|
||||
|
||||
{/* Tablo */}
|
||||
<div className="rounded-xl border overflow-hidden">
|
||||
<div className="bg-muted/30 p-3 flex gap-4">
|
||||
{[120, 80, 80, 70, 60].map((w, i) => (
|
||||
<Skeleton key={i} className="h-3" style={{ width: w }} />
|
||||
))}
|
||||
</div>
|
||||
{Array.from({ length: 8 }).map((_, i) => (
|
||||
<div key={i} className="border-t p-3 flex gap-4 items-center">
|
||||
<Skeleton className="h-10 w-10 rounded-md shrink-0" />
|
||||
<div className="flex-1 space-y-1.5">
|
||||
<Skeleton className="h-4 w-48" />
|
||||
<Skeleton className="h-3 w-32" />
|
||||
</div>
|
||||
<Skeleton className="h-4 w-20 hidden sm:block" />
|
||||
<Skeleton className="h-4 w-16 hidden md:block" />
|
||||
<Skeleton className="h-5 w-16 rounded-full" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user