2c6c074a06
Job lifecycle
- acceptJobAction (lab): pending → in_progress + currentStep=olcu
- advanceStepAction (lab): step ilerletir, son adım sonrası status=sent
- markDeliveredAction (clinic): sent → delivered
- cancelJobAction: pending iş iptali (her iki taraf)
- job_status_history her step transition'da idempotent kayıt
- Detay sayfası interactive panel + Aşama Geçmişi kartı
Job files (Appwrite Storage job-files bucket, 30MB/file)
- uploadJobFilesAction: çoklu dosya, mimeType'tan kind sınıflandırma
(scan/image/document), her iki team'e read permission, partial-fail
rollback (storage + row temizliği)
- deleteJobFileAction: yetkilendirilmiş silme, file + row birlikte
- JobFilesPanel: client-side select + upload + liste + indir + sil
- next.config bodySizeLimit 3mb → 100mb (toplu yükleme için)
Finance sync (idempotent)
- syncFinanceForJob helper: sent/delivered transition'larında klinik
payable + lab receivable rows (jobId+tenantId+type unique kontrolü,
her tarafta tek satır garanti)
- markFinancePaidAction / reopenFinanceAction: manuel ödendi/geri al
- /finance sayfası: stat kartlar (bekleyen alacak/borç, aylık gelir/gider)
+ hareketler tablosu, role-aware kopyalar
- Memory rule [[feedback_cross_entity_sync_helpers]]: best-effort, never
re-throws
Notifications
- createNotification helper, connection (request/approve) ve job
(create/accept/sent/delivered) eventlerinde tetikleniyor
- /notifications sayfası + tek tek / hepsi okundu işaretle
- Header'a Bell ikonu + okunmamış count badge (layout SSR'de besler)
- Middleware PROTECTED_PREFIXES'e /notifications ekli
65 lines
1.3 KiB
TypeScript
65 lines
1.3 KiB
TypeScript
import type { NextConfig } from "next";
|
|
|
|
const nextConfig: NextConfig = {
|
|
experimental: {
|
|
optimizePackageImports: ["lucide-react", "@radix-ui/react-icons"],
|
|
serverActions: {
|
|
// Job files bucket caps individual files at 30MB; raise overall body
|
|
// limit to allow batch uploads.
|
|
bodySizeLimit: "100mb",
|
|
},
|
|
},
|
|
turbopack: {},
|
|
|
|
// Image optimization
|
|
images: {
|
|
remotePatterns: [
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'ui.shadcn.com',
|
|
},
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'images.unsplash.com',
|
|
},
|
|
],
|
|
formats: ['image/webp', 'image/avif'],
|
|
},
|
|
|
|
// Headers for better security and performance
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: '/(.*)',
|
|
headers: [
|
|
{
|
|
key: 'X-Frame-Options',
|
|
value: 'DENY',
|
|
},
|
|
{
|
|
key: 'X-Content-Type-Options',
|
|
value: 'nosniff',
|
|
},
|
|
{
|
|
key: 'Referrer-Policy',
|
|
value: 'origin-when-cross-origin',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
},
|
|
|
|
// Redirects for better SEO
|
|
async redirects() {
|
|
return [
|
|
{
|
|
source: '/home',
|
|
destination: '/dashboard',
|
|
permanent: true,
|
|
},
|
|
];
|
|
},
|
|
};
|
|
|
|
export default nextConfig;
|