+ {/* Unread Alerts Section */}
+ {unreadAlerts.length > 0 && (
+
+
+
+ Unread Alerts ({unreadAlerts.length})
+
+
+ {unreadAlerts.map((notification) => (
+
+
+
+
+
+ {notification.title}
+
+
+ Alert
+
+
+
+
+
+ {formatDate(new Date(notification.display_date))}
+ {notification.display_time
+ ? ` at ${notification.display_time}`
+ : ''}
+
+
+
+
+ {notification.text}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Other Notifications */}
+ {otherNotifications.length > 0 && (
+
+ {unreadAlerts.length > 0 && (
+
+ All Notifications
+
+ )}
+
+ {otherNotifications.map((notification) => {
+ const isRead = notification.is_read || readIds.has(notification.id);
+ return (
+
+
+
+
+
+ {notification.title}
+
+ {notification.is_alert && (
+
+ Alert
+
+ )}
+ {isRead && (
+
+ Read
+
+ )}
+
+ {notification.is_alert && !isRead && (
+
+ )}
+
+
+ {formatDate(new Date(notification.display_date))}
+ {notification.display_time
+ ? ` at ${notification.display_time}`
+ : ''}
+
+
+
+
+ {notification.text}
+
+
+
+ );
+ })}
+
+
+ )}
+
+ );
+}
diff --git a/src/lib/storage.ts b/src/lib/storage.ts
new file mode 100644
index 0000000..9e5e1f0
--- /dev/null
+++ b/src/lib/storage.ts
@@ -0,0 +1,10 @@
+import path from 'path';
+
+/**
+ * Get the base storage path for invoice PDF files.
+ * In production, this should point to the mounted storage volume.
+ * In development, falls back to a local directory.
+ */
+export function getInvoiceStoragePath(): string {
+ return process.env.INVOICE_STORAGE_PATH || path.join(process.cwd(), 'storage', 'invoices');
+}
diff --git a/src/services/invoices.ts b/src/services/invoices.ts
new file mode 100644
index 0000000..9fd7a29
--- /dev/null
+++ b/src/services/invoices.ts
@@ -0,0 +1,68 @@
+import { db } from '@/lib/db';
+import { getInvoiceStoragePath } from '@/lib/storage';
+import type { InvoiceEntry } from '@/types/invoices';
+import fs from 'fs/promises';
+import path from 'path';
+
+/**
+ * Get all invoices for a company.
+ * Filters out ignored and replaced entries.
+ * Returns newest first.
+ */
+export async function getInvoicesForCompany(
+ companyId: string
+): Promise