Customer dashboard: order tracking + portal login

- New page: /portal/dashboard/ — customer can view all orders
- Auth: cookie-based login, shows auth modal if not logged in
- Orders grouped by batch, filtered by DOT/FCC tabs
- Shows service name, amount, discount, status badge, payment method
- Portal API: /api/v1/portal/me now returns compliance_orders

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
justin 2026-05-30 14:20:58 -05:00
parent 1cfda2c119
commit 6f3ad1b686
2 changed files with 420 additions and 1 deletions

View file

@ -18,7 +18,7 @@ router.use(requireCustomerAuth);
router.get("/me", async (req: Request, res: Response) => {
const { customerId } = req.customer!;
try {
const [custR, ordersR, addrR, dirR] = await Promise.all([
const [custR, ordersR, complianceR, addrR, dirR] = await Promise.all([
// Customer info
pool.query<{ id: number; email: string; name: string; company: string; phone: string }>(
`SELECT id, email, name, company, phone FROM customers WHERE id = $1`,
@ -41,6 +41,18 @@ router.get("/me", async (req: Request, res: Response) => {
LIMIT 20`,
[customerId, req.customer!.email]
),
// Compliance orders (DOT + FCC)
pool.query(
`SELECT order_number, batch_id, service_slug, service_name,
service_fee_cents, discount_cents, discount_code,
surcharge_cents, payment_status, payment_method,
created_at, paid_at
FROM compliance_orders
WHERE customer_email = $1
ORDER BY created_at DESC
LIMIT 50`,
[req.customer!.email]
),
// Saved addresses
pool.query<{
id: number; label: string; street: string; street2: string;
@ -77,6 +89,7 @@ router.get("/me", async (req: Request, res: Response) => {
res.json({
customer,
orders: ordersR.rows,
compliance_orders: complianceR.rows,
addresses: addrR.rows,
directors: dirR.rows.map((d) => ({
id: d.id,

File diff suppressed because one or more lines are too long