feat: all core modules — properties, customers, searches, matches, presentations, activities, investors + public sunum page

- Server actions: property/customer/search/presentation/activity/investor CRUD
- Matching engine: matchPropertyToSearches + syncMatchesForSearch on search save
- UI: form sheets + table clients for all modules
- Public /sunum/[token] page (no auth) with property card grid + expiry check
- All pages force-dynamic for auth guard compatibility
This commit is contained in:
egecankomur
2026-05-05 12:03:48 +03:00
parent 2f17c342ca
commit 4ef0482732
34 changed files with 3174 additions and 36 deletions
+37 -4
View File
@@ -1,8 +1,41 @@
export default function Page() {
export const dynamic = "force-dynamic";
import { Query } from "node-appwrite";
import { requireTenant } from "@/lib/appwrite/tenant-guard";
import { listCustomers } from "@/lib/appwrite/customer-queries";
import { listProperties } from "@/lib/appwrite/property-queries";
import { DATABASE_ID, TABLES, type Presentation } from "@/lib/appwrite/schema";
import { createAdminClient } from "@/lib/appwrite/server";
import { PresentationsClient } from "@/components/presentations/presentations-client";
export default async function PresentationsPage() {
const ctx = await requireTenant();
const { tablesDB } = createAdminClient();
const [customers, properties, presResult] = await Promise.all([
listCustomers(ctx.tenantId),
listProperties(ctx.tenantId),
tablesDB.listRows({
databaseId: DATABASE_ID,
tableId: TABLES.presentations,
queries: [
Query.equal("tenantId", ctx.tenantId),
Query.orderDesc("$createdAt"),
Query.limit(200),
],
}),
]);
const presentations = presResult.rows as unknown as Presentation[];
return (
<div className="flex flex-1 flex-col gap-4 p-4">
<h1 className="text-2xl font-bold capitalize">presentations</h1>
<p className="text-muted-foreground">Yakında...</p>
<div className="flex flex-1 flex-col gap-4 p-4 md:p-6">
<PresentationsClient
initialPresentations={presentations}
customers={customers}
properties={properties}
/>
</div>
);
}