diff --git a/app/(dashboard)/deadlines/page.tsx b/app/(dashboard)/deadlines/page.tsx
index 4e6797c2..ba21e231 100644
--- a/app/(dashboard)/deadlines/page.tsx
+++ b/app/(dashboard)/deadlines/page.tsx
@@ -4,9 +4,9 @@ import { useState, useEffect, useCallback } from 'react'
import Link from 'next/link'
import { createClient } from '@/lib/supabase/client'
import { useToast } from '@/components/ui/use-toast'
+import { ToastAction } from '@/components/ui/toast'
import { DeadlineList } from '@/components/deadlines/DeadlineList'
-import { Card, CardContent } from '@/components/ui/card'
-import { Badge } from '@/components/ui/badge'
+import { PageHeader } from '@/components/ui/page-header'
import { AlertTriangle, ArrowRight } from 'lucide-react'
import type { Deadline } from '@/types'
@@ -25,7 +25,6 @@ export default function DeadlinesPage() {
try {
const today = new Date().toISOString().split('T')[0]
- // Fetch all data in parallel
const [deadlinesRes, customersRes, overdueRes] = await Promise.all([
supabase.from('deadlines').select('*, customer:customers(name)').order('due_date', { ascending: true }),
supabase.from('customers').select('id, name').order('name', { ascending: true }),
@@ -92,11 +91,14 @@ export default function DeadlinesPage() {
}
const handleDeadlineToggle = async (deadline: Deadline) => {
+ const wasCompleted = deadline.is_completed
+ const newCompleted = !wasCompleted
+
try {
const response = await fetch(`/api/deadlines/${deadline.id}/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ is_completed: !deadline.is_completed }),
+ body: JSON.stringify({ is_completed: newCompleted }),
})
if (!response.ok) {
@@ -104,11 +106,33 @@ export default function DeadlinesPage() {
throw new Error(result.error || 'Failed to toggle deadline')
}
- toast({
- title: deadline.is_completed ? 'Markerad som ej klar' : 'Markerad som klar',
- })
-
fetchData()
+
+ if (newCompleted) {
+ toast({
+ title: `"${deadline.title}" markerad som klar`,
+ action: (
+
{
+ try {
+ await fetch(`/api/deadlines/${deadline.id}/complete`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ is_completed: false }),
+ })
+ } catch {
+ toast({
+ title: 'Kunde inte ångra',
+ variant: 'destructive',
+ })
+ }
+ }}>
+ Ångra
+
+ ),
+ })
+ } else {
+ toast({ title: `"${deadline.title}" markerad som ej klar` })
+ }
} catch (error) {
toast({
title: 'Kunde inte uppdatera status',
@@ -157,10 +181,7 @@ export default function DeadlinesPage() {
throw new Error(result.error || 'Failed to delete deadline')
}
- toast({
- title: 'Deadline borttagen',
- })
-
+ toast({ title: 'Deadline borttagen' })
fetchData()
} catch (error) {
toast({
@@ -174,35 +195,21 @@ export default function DeadlinesPage() {
if (isLoading) {
return (
-
-
Deadlines
-
- {/* Overdue alert skeleton */}
-
- {/* Deadline list skeleton */}
-
+
+
{[1, 2, 3, 4].map((i) => (
-
-
))}
@@ -213,32 +220,23 @@ export default function DeadlinesPage() {
return (
-
-
Deadlines
-
+
+ {/* Overdue invoices alert */}
{overdueInvoices.count > 0 && (
-
-
-
-
-
-
-
-
Forfallna fakturor
-
- {overdueInvoices.count} st totalt{' '}
- {overdueInvoices.total.toLocaleString('sv-SE')} kr
-
-
-
-
-
{overdueInvoices.count}
-
-
-
-
-
+
+
+
+
+
+ {overdueInvoices.count} förfallna fakturor
+
+ {overdueInvoices.total.toLocaleString('sv-SE')} kr
+
+
+
+
+
)}
diff --git a/app/(dashboard)/expenses/new/page.tsx b/app/(dashboard)/expenses/new/page.tsx
index 42c043df..04427e23 100644
--- a/app/(dashboard)/expenses/new/page.tsx
+++ b/app/(dashboard)/expenses/new/page.tsx
@@ -81,6 +81,7 @@ export default function NewExpensePage() {
const [pendingData, setPendingData] = useState
(null)
const [showNewSupplier, setShowNewSupplier] = useState(false)
const [isCreatingSupplier, setIsCreatingSupplier] = useState(false)
+ const [pendingSupplierSelect, setPendingSupplierSelect] = useState(null)
const [advancedOpen, setAdvancedOpen] = useState(false)
const [newSupplier, setNewSupplier] = useState({
name: '',
@@ -146,6 +147,14 @@ export default function NewExpensePage() {
}
}, [watchedSupplierId, suppliers])
+ // Auto-select newly created supplier once it's in the list
+ useEffect(() => {
+ if (pendingSupplierSelect && suppliers.find((s) => s.id === pendingSupplierSelect)) {
+ setValue('supplier_id', pendingSupplierSelect, { shouldDirty: true, shouldValidate: true })
+ setPendingSupplierSelect(null)
+ }
+ }, [suppliers, pendingSupplierSelect, setValue])
+
async function fetchSuppliers() {
const res = await fetch('/api/suppliers')
const { data } = await res.json()
@@ -220,7 +229,7 @@ export default function NewExpensePage() {
} else {
const created = result.data as Supplier
setSuppliers((prev) => [...prev, created].sort((a, b) => a.name.localeCompare(b.name)))
- setValue('supplier_id', created.id)
+ setPendingSupplierSelect(created.id)
setShowNewSupplier(false)
setNewSupplier({ name: '', supplier_type: 'swedish_business', org_number: '', bankgiro: '', plusgiro: '', default_expense_account: '' })
toast({ title: 'Leverantör skapad', description: created.name })
diff --git a/app/(dashboard)/invoices/page.tsx b/app/(dashboard)/invoices/page.tsx
index 9894da30..00fd8359 100644
--- a/app/(dashboard)/invoices/page.tsx
+++ b/app/(dashboard)/invoices/page.tsx
@@ -267,7 +267,7 @@ export default function InvoicesPage() {
return (
diff --git a/components/dashboard/SandboxBanner.tsx b/components/dashboard/SandboxBanner.tsx
index a25db48f..016f1f56 100644
--- a/components/dashboard/SandboxBanner.tsx
+++ b/components/dashboard/SandboxBanner.tsx
@@ -18,19 +18,19 @@ export function SandboxBanner() {
}
return (
-
-
- Sandlådemiljö — dina data raderas automatiskt efter 24 timmar
+
+
+ Sandlådemiljö — data raderas efter 24h