feat(modules): connections, products, jobs (list/form/detail-placeholder)
Connections (clinic ↔ lab)
- request via member number, approve/reject (counterparty), cancel pending,
delete approved
- permission rows opened to both teams; audit log for every mutation
- /connections page: own code card, request form, pending inbound/outbound
tables, approved connections table with delete confirm
Products (lab catalog)
- createProstheticAction + update + archive/restore + delete (lab-only)
- zod validation, dev-mode error surfacing
- /products page: catalog table + add form + edit dialog. Hidden from
clinic accounts via requireTenantKind.
Jobs (work orders)
- createJobAction (clinic-only) — checks approved connection before write,
permissions opened to both clinic and lab teams
- listInboundJobs (lab perspective), listOutboundJobs (clinic perspective),
listApprovedLabsForClinic for the new-job form
- /jobs/inbound + /jobs/outbound tables with role-aware copy
- /jobs/new full form (lab select, patient code, prosthetic type, member
count, color, due date, price/currency, description)
- /jobs/[jobId] placeholder detail page with stepper visualisation;
status/step updates and file upload come next session
All new mutations follow the memory rules: schema-checked row payloads,
admin client behind requireTenant + requireRole/requireTenantKind, audit
log calls best-effort, no empty-string Radix Select values.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import "server-only";
|
||||
|
||||
import { Query } from "node-appwrite";
|
||||
|
||||
import { DATABASE_ID, TABLES, type Prosthetic } from "./schema";
|
||||
import { createAdminClient } from "./server";
|
||||
|
||||
export async function listProsthetics(tenantId: string): Promise<Prosthetic[]> {
|
||||
const { tablesDB } = createAdminClient();
|
||||
const result = await tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
tableId: TABLES.prosthetics,
|
||||
queries: [
|
||||
Query.equal("tenantId", tenantId),
|
||||
Query.orderAsc("name"),
|
||||
Query.limit(200),
|
||||
],
|
||||
});
|
||||
return result.rows as unknown as Prosthetic[];
|
||||
}
|
||||
|
||||
export async function listActiveProsthetics(tenantId: string): Promise<Prosthetic[]> {
|
||||
const { tablesDB } = createAdminClient();
|
||||
const result = await tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
tableId: TABLES.prosthetics,
|
||||
queries: [
|
||||
Query.equal("tenantId", tenantId),
|
||||
Query.notEqual("archived", true),
|
||||
Query.orderAsc("name"),
|
||||
Query.limit(200),
|
||||
],
|
||||
});
|
||||
return result.rows as unknown as Prosthetic[];
|
||||
}
|
||||
Reference in New Issue
Block a user