Add descriptive error messages across all API routes and toast notifications on client pages
Build & Auto-Repair / build (push) Has been cancelled

- 86 catch blocks in 49 API route files now return the actual error message via error.message
- 14 campaign/lead/config catch blocks that lacked console.error now log errors
- 17 client pages/components now show toast.error notifications on API failures
- Silent .catch(() => {}) and finally-only try blocks now surface errors to users
This commit is contained in:
2026-07-01 15:20:30 +02:00
parent 727dcddf37
commit 3fe32d923e
76 changed files with 344 additions and 155 deletions
+5 -4
View File
@@ -12,6 +12,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
ArrowLeft, Plus, Trash2, Send, Play, Pause, Users, Mail, Clock,
} from "lucide-react"
import { toast } from "sonner"
export default function CampaignDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = use(params)
@@ -29,7 +30,7 @@ export default function CampaignDetailPage({ params }: { params: Promise<{ id: s
try {
const res = await fetch(`/api/campaigns/${id}`)
if (res.ok) setCampaign(await res.json())
} catch { /* ignore */ }
} catch (e) { console.error("Failed to load campaign", e); toast.error("Failed to load campaign") }
setLoading(false)
}
@@ -53,7 +54,7 @@ export default function CampaignDetailPage({ params }: { params: Promise<{ id: s
})
setNewStep({ subject: "", bodyText: "", delayDays: 3 })
fetchCampaign()
} catch { /* ignore */ }
} catch (e) { console.error("Failed to add step", e); toast.error("Failed to add step") }
setAddingStep(false)
}
@@ -68,7 +69,7 @@ export default function CampaignDetailPage({ params }: { params: Promise<{ id: s
setLeadSearch("")
setSearchResults([])
fetchCampaign()
} catch { /* ignore */ }
} catch (e) { console.error("Failed to subscribe leads", e); toast.error("Failed to subscribe leads") }
setSubscribing(false)
}
@@ -78,7 +79,7 @@ export default function CampaignDetailPage({ params }: { params: Promise<{ id: s
const res = await fetch(`/api/campaigns/${id}/send`, { method: "POST" })
const data = await res.json()
if (data.sent > 0) fetchCampaign()
} catch { /* ignore */ }
} catch (e) { console.error("Failed to send campaign", e); toast.error("Failed to send campaign") }
setSending(false)
}
+2 -1
View File
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Card } from "@/components/ui/card"
import { ArrowLeft } from "lucide-react"
import { toast } from "sonner"
export default function NewCampaignPage() {
const router = useRouter()
@@ -25,7 +26,7 @@ export default function NewCampaignPage() {
})
const data = await res.json()
if (data.id) router.push(`/campaigns/${data.id}`)
} catch { /* ignore */ }
} catch (e) { console.error("Campaign create error:", e); toast.error("Failed to create campaign") }
setSaving(false)
}
+2 -1
View File
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Plus, Mail, Users, Layers, Calendar } from "lucide-react"
import { toast } from "sonner"
const statusColors: Record<string, string> = {
draft: "bg-zinc-100 text-zinc-700 border-zinc-300",
@@ -24,7 +25,7 @@ export default function CampaignsPage() {
fetch("/api/campaigns")
.then(r => r.json())
.then(d => { if (Array.isArray(d)) setCampaigns(d); else setCampaigns([]) })
.catch(() => setCampaigns([]))
.catch((e) => { console.error("Failed to load campaigns", e); toast.error("Failed to load campaigns"); setCampaigns([]) })
.finally(() => setLoading(false))
}, [])
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Card } from "@/components/ui/card"
import { GripVertical, Plus, User, Building2, Mail, Phone, Hash } from "lucide-react"
import { toast } from "sonner"
interface KanbanLead {
id: string
@@ -57,6 +58,7 @@ export default function KanbanPage() {
const data = await res.json()
setColumns(data)
} catch (e) {
toast.error("Failed to load kanban data")
console.error("Failed to load kanban", e)
} finally {
setLoading(false)
@@ -98,6 +100,7 @@ export default function KanbanPage() {
body: JSON.stringify({ status: toStatus }),
})
} catch (e) {
toast.error("Failed to update lead status")
console.error("Failed to update lead status", e)
fetchKanban()
}
+3 -1
View File
@@ -29,6 +29,7 @@ import { ArrowLeft } from "lucide-react"
import { User } from "@/types"
import { useNotifications } from "@/providers/notification-provider"
import { LEAD_SOURCES, LEAD_STATUSES } from "@/lib/constants"
import { toast } from "sonner"
const leadFormSchema = z.object({
companyName: z.string().min(1, "Company name is required"),
@@ -53,7 +54,7 @@ export default function CreateLeadPage() {
fetch("/api/users")
.then((r) => r.json())
.then((data) => setUsers(data.users || []))
.catch(() => {})
.catch((e) => { console.error("Failed to load users", e); toast.error("Failed to load users") })
}, [])
const form = useForm<LeadFormValues>({
@@ -87,6 +88,7 @@ export default function CreateLeadPage() {
addNotification("lead_created", "New Lead Created", `${values.companyName}${values.contactName}`, `/leads/${data.id}`)
router.push("/leads")
} catch (e) {
toast.error("Failed to create lead")
console.error("Create lead error:", e)
} finally {
setSaving(false)
+2 -1
View File
@@ -7,6 +7,7 @@ import { LeadsTable } from "@/components/leads/leads-table"
import { LeadsTableToolbar } from "@/components/leads/leads-table-toolbar"
import { Button } from "@/components/ui/button"
import { Columns3 } from "lucide-react"
import { toast } from "sonner"
import { Lead } from "@/types"
export default function LeadsPage() {
@@ -30,7 +31,7 @@ export default function LeadsPage() {
setLeadsData(data)
setLoading(false)
})
.catch(() => setLoading(false))
.catch((e) => { console.error("Failed to load leads", e); toast.error("Failed to load leads"); setLoading(false) })
}, [search, statusFilter, periodFilter])
return (
@@ -20,6 +20,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { toast } from "sonner"
interface Milestone {
id: string
@@ -82,6 +83,7 @@ export default function ProjectDetailPage() {
setMilestones(await mRes.json())
setStatuses(await sRes.json())
} catch (e) {
toast.error("Failed to load project")
console.error("Failed to load project", e)
} finally {
setLoading(false)
@@ -91,21 +93,31 @@ export default function ProjectDetailPage() {
useEffect(() => { fetchProject() }, [fetchProject])
const updateProjectStatus = async (statusId: string) => {
try {
await fetch(`/api/projects/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ statusId }),
})
fetchProject()
} catch (e) {
console.error("Failed to update project status", e)
toast.error("Failed to update project status")
}
}
const updateMilestoneStatus = async (milestoneId: string, status: string) => {
try {
await fetch(`/api/milestones/${milestoneId}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ status }),
})
fetchProject()
} catch (e) {
console.error("Failed to update milestone status", e)
toast.error("Failed to update milestone status")
}
}
const addMilestone = async () => {
@@ -119,6 +131,9 @@ export default function ProjectDetailPage() {
})
setNewMilestoneName("")
fetchProject()
} catch (e) {
console.error("Failed to add milestone", e)
toast.error("Failed to add milestone")
} finally {
setAddingMilestone(false)
}
@@ -140,6 +155,7 @@ export default function ProjectDetailPage() {
setNewTaskInputs((prev) => ({ ...prev, [milestoneId]: "" }))
fetchProject()
} catch (e) {
toast.error("Failed to add task")
console.error("Failed to add task", e)
}
}
+8 -3
View File
@@ -22,6 +22,7 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { toast } from "sonner"
interface Project {
id: string
@@ -65,6 +66,7 @@ export default function ProjectsPage() {
const data = res.ok ? await res.json() : []
setProjects(Array.isArray(data) ? data : [])
} catch (e) {
toast.error("Failed to load projects")
console.error("Failed to load projects", e)
setProjects([])
} finally {
@@ -75,7 +77,7 @@ export default function ProjectsPage() {
useEffect(() => { fetchProjects() }, [search, statusFilter])
useEffect(() => {
fetch("/api/project-statuses").then(r => r.json()).then((d) => setStatuses(Array.isArray(d) ? d : [])).catch(() => {})
fetch("/api/project-statuses").then(r => r.json()).then((d) => setStatuses(Array.isArray(d) ? d : [])).catch((e) => { console.error("Failed to load project statuses", e); toast.error("Failed to load project statuses") })
}, [])
const formatDate = (d: string) => d ? new Date(d).toLocaleDateString() : "—"
@@ -168,8 +170,8 @@ function NewProjectDialog({ statuses, onCreated }: { statuses: ProjectStatus[];
useEffect(() => {
if (!open) return
fetch("/api/customers?limit=100").then(r => r.json()).then(d => setCustomers(Array.isArray(d) ? d : [])).catch(() => {})
fetch("/api/users").then(r => r.json()).then(d => setUsers(d.users || [])).catch(() => {})
fetch("/api/customers?limit=100").then(r => r.json()).then(d => setCustomers(Array.isArray(d) ? d : [])).catch((e) => { console.error("Failed to load customers", e); toast.error("Failed to load customers") })
fetch("/api/users").then(r => r.json()).then(d => setUsers(d.users || [])).catch((e) => { console.error("Failed to load users", e); toast.error("Failed to load users") })
}, [open])
const handleSubmit = async () => {
@@ -194,6 +196,9 @@ function NewProjectDialog({ statuses, onCreated }: { statuses: ProjectStatus[];
setName(""); setDescription(""); setCustomerId(""); setOwnerId(""); setStartDate(""); setTargetEndDate(""); setBudget("")
onCreated()
}
} catch (e) {
console.error("Failed to create project", e)
toast.error("Failed to create project")
} finally {
setSaving(false)
}
@@ -15,6 +15,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { toast } from "sonner"
export default function ProposalDetailPage() {
const { id } = useParams<{ id: string }>()
@@ -35,6 +36,7 @@ export default function ProposalDetailPage() {
setProposal(await pRes.json())
setStatuses(await sRes.json())
} catch (e) {
toast.error("Failed to load proposal")
console.error("Failed to load proposal", e)
} finally {
setLoading(false)
@@ -44,12 +46,17 @@ export default function ProposalDetailPage() {
useEffect(() => { fetchProposal() }, [fetchProposal])
const updateStatus = async (statusId: string) => {
try {
await fetch(`/api/proposals/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ statusId }),
})
fetchProposal()
} catch (e) {
console.error("Failed to update proposal status", e)
toast.error("Failed to update proposal status")
}
}
const handleSign = async () => {
@@ -62,6 +69,9 @@ export default function ProposalDetailPage() {
body: JSON.stringify({ name: signName, email: signEmail }),
})
if (res.ok) fetchProposal()
} catch (e) {
console.error("Failed to sign proposal", e)
toast.error("Failed to sign proposal")
} finally {
setSigning(false)
}
+4 -2
View File
@@ -14,6 +14,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { toast } from "sonner"
interface LineItem {
id: string
@@ -39,8 +40,8 @@ export default function NewProposalPage() {
const [saving, setSaving] = useState(false)
useEffect(() => {
fetch("/api/leads?limit=100").then((r) => r.json()).then(setLeads).catch(() => {})
fetch("/api/customers?limit=100").then((r) => r.json()).then(setCustomers).catch(() => {})
fetch("/api/leads?limit=100").then((r) => r.json()).then(setLeads).catch((e) => { console.error("Failed to load leads", e); toast.error("Failed to load leads") })
fetch("/api/customers?limit=100").then((r) => r.json()).then(setCustomers).catch((e) => { console.error("Failed to load customers", e); toast.error("Failed to load customers") })
}, [])
const addItem = () => {
@@ -107,6 +108,7 @@ export default function NewProposalPage() {
router.push(`/proposals/${data.id}`)
} catch (e) {
toast.error("Failed to create proposal")
console.error("Failed to create proposal", e)
} finally {
setSaving(false)
+3 -2
View File
@@ -15,6 +15,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { toast } from "sonner"
export default function ProposalsPage() {
const router = useRouter()
@@ -31,12 +32,12 @@ export default function ProposalsPage() {
fetch(`/api/proposals?${params}`)
.then((r) => r.json())
.then(setProposals)
.catch(() => {})
.catch((e) => { console.error("Failed to load proposals", e); toast.error("Failed to load proposals") })
.finally(() => setLoading(false))
}, [search, statusFilter])
useEffect(() => {
fetch("/api/proposal-statuses").then((r) => r.json()).then(setStatuses).catch(() => {})
fetch("/api/proposal-statuses").then((r) => r.json()).then(setStatuses).catch((e) => { console.error("Failed to load proposal statuses", e); toast.error("Failed to load proposal statuses") })
}, [])
const formatCurrency = (n: number) => n ? `R${Number(n).toLocaleString()}` : "R0"
@@ -13,6 +13,7 @@ import {
SelectValue,
} from "@/components/ui/select"
import { Users, Clock, Briefcase, AlertTriangle, TrendingUp } from "lucide-react"
import { toast } from "sonner"
interface Member {
id: string
@@ -81,7 +82,7 @@ export default function ResourcePlanningPage() {
fetch(`/api/resource-planning?period=${period}`)
.then(r => r.json())
.then(d => { setMembers(d.members || []); setTotals(d.totals || null) })
.catch(() => {})
.catch((e) => { console.error("Failed to load resource data", e); toast.error("Failed to load resource data") })
.finally(() => setLoading(false))
}, [period])
@@ -7,6 +7,7 @@ import { Input } from "@/components/ui/input"
import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Play, Square, Plus, Trash2, Clock, Briefcase, User, TrendingUp, DollarSign } from "lucide-react"
import { toast } from "sonner"
interface TimeEntry {
id: string
@@ -59,6 +60,7 @@ export default function TimeTrackingPage() {
setSummary(sData?.totals ? sData : null)
setProjects(Array.isArray(pData) ? pData : [])
} catch (e) {
toast.error("Failed to load time data")
console.error("Failed to load time data", e)
setEntries([])
setProjects([])
@@ -105,6 +107,7 @@ export default function TimeTrackingPage() {
setTimerSeconds(0)
fetchData()
} catch (e) {
toast.error("Failed to save time entry")
console.error("Failed to save time entry", e)
}
}
@@ -135,14 +138,22 @@ export default function TimeTrackingPage() {
setManualRate("")
setShowManual(false)
fetchData()
} catch (e) {
console.error("Failed to save time entry", e)
toast.error("Failed to save time entry")
} finally {
setSaving(false)
}
}
const deleteEntry = async (id: string) => {
try {
await fetch(`/api/time-entries?id=${id}`, { method: "DELETE" })
fetchData()
} catch (e) {
console.error("Failed to delete time entry", e)
toast.error("Failed to delete time entry")
}
}
const formatDuration = (mins: number) => {
+2 -1
View File
@@ -141,8 +141,9 @@ export async function POST(request: NextRequest) {
return response
} catch (error) {
console.error("Login error:", error)
const message = error instanceof Error ? error.message : "Authentication service unavailable."
return NextResponse.json(
{ error: "Authentication service unavailable." },
{ error: message },
{ status: 503 }
)
}
+2 -1
View File
@@ -11,8 +11,9 @@ export async function POST() {
})
} catch (error) {
console.error("Logout error:", error)
const message = error instanceof Error ? error.message : "Logout failed."
return new Response(
JSON.stringify({ error: "Logout failed." }),
JSON.stringify({ error: message }),
{ status: 500, headers: { "Content-Type": "application/json" } }
)
}
+2 -1
View File
@@ -10,8 +10,9 @@ export async function GET() {
return NextResponse.json({ user }, { status: 200 })
} catch (error) {
console.error("Auth me error:", error)
const message = error instanceof Error ? error.message : "Authentication service unavailable."
return NextResponse.json(
{ error: "Authentication service unavailable." },
{ error: message },
{ status: 503 }
)
}
+2 -1
View File
@@ -59,6 +59,7 @@ export async function POST(request: NextRequest) {
}, { status: 200 })
} catch (error) {
console.error("Password recovery error:", error)
return NextResponse.json({ error: "Recovery service unavailable." }, { status: 503 })
const message = error instanceof Error ? error.message : "Recovery service unavailable."
return NextResponse.json({ error: message }, { status: 503 })
}
}
+2 -1
View File
@@ -64,6 +64,7 @@ export async function PATCH(request: NextRequest, { params: routeParams }: { par
return NextResponse.json({ success: true }, { status: 200 })
} catch (error) {
console.error("Error updating bug report:", error)
return NextResponse.json({ error: "Failed to update bug report." }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update bug report."
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -34,7 +34,8 @@ export async function POST(request: NextRequest) {
}, { status: 201 })
} catch (error) {
console.error("Error creating bug report:", error)
return NextResponse.json({ error: "Failed to submit bug report." }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to submit bug report."
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -113,6 +114,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ reports }, { status: 200 })
} catch (error) {
console.error("Error fetching bug reports:", error)
return NextResponse.json({ error: "Failed to fetch bug reports." }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to fetch bug reports."
return NextResponse.json({ error: message }, { status: 500 })
}
}
+3 -1
View File
@@ -16,6 +16,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
)
return NextResponse.json(result.rows)
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Campaign logs GET error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+9 -3
View File
@@ -31,7 +31,9 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ ...campaign.rows[0], steps: steps.rows, subscribers: subscribers.rows })
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Campaign GET error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -55,7 +57,9 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
await query(`UPDATE email_campaigns SET ${fields.join(", ")} WHERE id = $${idx}`, values)
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Campaign PATCH error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -67,6 +71,8 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
await query("UPDATE email_campaigns SET deleted_at = NOW() WHERE id = $1", [id])
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Campaign DELETE error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -46,7 +46,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ success: true, sent })
} catch (error) {
console.error("Campaign send error:", error)
return NextResponse.json({ error: "Failed to send" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to send"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -2
View File
@@ -10,7 +10,9 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
const result = await query("SELECT * FROM email_campaign_steps WHERE campaign_id = $1 ORDER BY step_order", [id])
return NextResponse.json(result.rows)
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Steps GET error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -31,6 +33,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
)
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Steps POST error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -30,6 +30,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ error: "leadIds array required" }, { status: 400 })
} catch (error) {
return NextResponse.json({ error: "Failed" }, { status: 500 })
console.error("Campaign subscribe POST error:", error)
const message = error instanceof Error ? error.message : "Failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -2
View File
@@ -17,7 +17,9 @@ export async function GET() {
)
return NextResponse.json(result.rows)
} catch (error) {
return NextResponse.json({ error: "Failed to load campaigns" }, { status: 500 })
console.error("Campaigns GET error:", error)
const message = error instanceof Error ? error.message : "Failed to load campaigns"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -33,6 +35,8 @@ export async function POST(request: NextRequest) {
)
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
return NextResponse.json({ error: "Failed to create campaign" }, { status: 500 })
console.error("Campaigns POST error:", error)
const message = error instanceof Error ? error.message : "Failed to create campaign"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -80,6 +80,7 @@ export async function DELETE(
})
} catch (error) {
console.error("[voice-delete] Error:", error)
return NextResponse.json({ error: "Unable to delete voice note. Please try again." }, { status: 500 })
const message = error instanceof Error ? error.message : "Unable to delete voice note. Please try again."
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -76,7 +76,8 @@ export async function GET(
return NextResponse.json({ messages })
} catch (error) {
console.error("Messages error:", error)
return NextResponse.json({ error: "Failed to load messages" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load messages"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -160,7 +161,8 @@ export async function POST(
})
} catch (error) {
console.error("Send message error:", error)
return NextResponse.json({ error: "Failed to send message" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to send message"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -198,7 +200,8 @@ export async function DELETE(
return NextResponse.json({ success: true })
} catch (error) {
console.error("Delete message error:", error)
return NextResponse.json({ error: "Failed to delete message" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete message"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -229,6 +232,7 @@ export async function PATCH(
return NextResponse.json({ success: true })
} catch (error) {
console.error("Edit message error:", error)
return NextResponse.json({ error: "Failed to edit message" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to edit message"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -28,6 +28,7 @@ export async function POST(
return NextResponse.json({ success: true })
} catch (error) {
console.error("Mark read error:", error)
return NextResponse.json({ error: "Failed to mark as read" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to mark as read"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -50,7 +50,8 @@ export async function GET() {
return NextResponse.json({ conversations })
} catch (error) {
console.error("Conversations error:", error)
return NextResponse.json({ error: "Failed to load conversations" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load conversations"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -115,7 +116,8 @@ export async function POST(request: NextRequest) {
})
} catch (error) {
console.error("Create conversation error:", error)
return NextResponse.json({ error: "Failed to create conversation" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create conversation"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+8 -4
View File
@@ -25,7 +25,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Custom fields API error:", error)
return NextResponse.json({ error: "Failed to load custom fields" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load custom fields"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -62,7 +63,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: "A field with this key already exists for this entity" }, { status: 409 })
}
console.error("Custom fields POST error:", error)
return NextResponse.json({ error: "Failed to create custom field" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create custom field"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -106,7 +108,8 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Custom fields PATCH error:", error)
return NextResponse.json({ error: "Failed to update custom field" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update custom field"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -120,6 +123,7 @@ export async function DELETE(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Custom fields DELETE error:", error)
return NextResponse.json({ error: "Failed to delete custom field" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete custom field"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -26,6 +26,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Customers API error:", error)
return NextResponse.json({ error: "Failed to load customers" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load customers"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -208,6 +208,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json(stats)
} catch (error) {
console.error("Dashboard API error:", error)
return NextResponse.json({ error: "Failed to load dashboard stats" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load dashboard stats"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -23,6 +23,7 @@ export async function GET() {
})) })
} catch (error) {
console.error("Emails GET error:", error)
return NextResponse.json({ error: "Failed to load sent emails" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load sent emails"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -28,6 +28,7 @@ export async function GET() {
return NextResponse.json({ users })
} catch (error) {
console.error("Event users error:", error)
return NextResponse.json({ error: "Failed to load users" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load users"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -49,6 +49,7 @@ export async function GET(_request: NextRequest, { params }: { params: Promise<{
})
} catch (error) {
console.error("ICS GET error:", error)
return NextResponse.json({ error: "Failed to generate calendar file" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to generate calendar file"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -159,7 +159,8 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
})
} catch (error) {
console.error("Events PATCH error:", error)
return NextResponse.json({ error: "Failed to update event" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update event"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -189,6 +190,7 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true })
} catch (error) {
console.error("Events DELETE error:", error)
return NextResponse.json({ error: "Failed to delete event" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete event"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -96,7 +96,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ events })
} catch (error) {
console.error("Events GET error:", error)
return NextResponse.json({ error: "Failed to load events" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load events"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -241,6 +242,7 @@ export async function POST(request: NextRequest) {
}, { status: 201 })
} catch (error) {
console.error("Events POST error:", error)
return NextResponse.json({ error: "Failed to create event" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create event"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -19,7 +19,9 @@ export async function POST(request: NextRequest) {
const inviteUrl = `${origin}/join/${token}`
return NextResponse.json({ token, inviteUrl })
} catch {
return NextResponse.json({ error: "Failed to generate invite" }, { status: 500 })
} catch (error) {
console.error("Invite generate error:", error)
const message = error instanceof Error ? error.message : "Failed to generate invite"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -39,7 +39,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ success: true })
} catch (error) {
console.error("Create note error:", error)
return NextResponse.json({ error: "Failed to create note" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create note"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -81,6 +82,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json(notes)
} catch (error) {
console.error("Lead notes API error:", error)
return NextResponse.json({ error: "Failed to load notes" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load notes"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -69,7 +69,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json(lead)
} catch (error) {
console.error("Lead detail API error:", error)
return NextResponse.json({ error: "Failed to load lead" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load lead"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -160,6 +161,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json({ success: true, id: result.rows[0].id })
} catch (error) {
console.error("Lead PATCH error:", error)
return NextResponse.json({ error: "Failed to update lead" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update lead"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -68,6 +68,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json(columns)
} catch (error) {
console.error("Kanban API error:", error)
return NextResponse.json({ error: "Failed to load kanban data" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load kanban data"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -3
View File
@@ -114,7 +114,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json(leads)
} catch (error) {
console.error("Leads API error:", error)
return NextResponse.json({ error: "Failed to load leads" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load leads"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -160,7 +161,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Leads POST error:", error)
return NextResponse.json({ error: "Failed to create lead" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create lead"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -187,6 +189,7 @@ export async function DELETE(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Leads DELETE error:", error)
return NextResponse.json({ error: "Failed to delete lead" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete lead"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+12 -4
View File
@@ -9,7 +9,9 @@ export async function GET() {
const result = await query("SELECT * FROM lead_scoring_config WHERE is_active = true ORDER BY weight DESC")
return NextResponse.json(result.rows)
} catch (error) {
return NextResponse.json({ error: "Failed to load scoring config" }, { status: 500 })
console.error("Scoring config GET error:", error)
const message = error instanceof Error ? error.message : "Failed to load scoring config"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -30,7 +32,9 @@ export async function POST(request: NextRequest) {
if (error?.constraint === "lead_scoring_config_feature_name_key") {
return NextResponse.json({ error: "Feature name already exists" }, { status: 409 })
}
return NextResponse.json({ error: "Failed to create feature" }, { status: 500 })
console.error("Scoring config POST error:", error)
const message = error instanceof Error ? error.message : "Failed to create feature"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -56,7 +60,9 @@ export async function PATCH(request: NextRequest) {
await query(`UPDATE lead_scoring_config SET ${fields.join(", ")} WHERE id = $${idx}`, values)
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json({ error: "Failed to update" }, { status: 500 })
console.error("Scoring config PATCH error:", error)
const message = error instanceof Error ? error.message : "Failed to update"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -72,6 +78,8 @@ export async function DELETE(request: NextRequest) {
await query("DELETE FROM lead_scoring_config WHERE id = $1", [id])
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json({ error: "Failed to delete" }, { status: 500 })
console.error("Scoring config DELETE error:", error)
const message = error instanceof Error ? error.message : "Failed to delete"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -83,6 +83,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, scored })
} catch (error) {
console.error("Lead scoring error:", error)
return NextResponse.json({ error: "Scoring failed" }, { status: 500 })
const message = error instanceof Error ? error.message : "Scoring failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -41,7 +41,8 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json({ success: true, id: result.rows[0].id })
} catch (error) {
console.error("Milestone PATCH error:", error)
return NextResponse.json({ error: "Failed to update milestone" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update milestone"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -55,6 +56,7 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true })
} catch (error) {
console.error("Milestone DELETE error:", error)
return NextResponse.json({ error: "Failed to delete milestone" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete milestone"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -21,7 +21,8 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json({ success: true })
} catch (error) {
console.error("Notification PATCH error:", error)
return NextResponse.json({ error: "Failed to mark notification as read" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to mark notification as read"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -44,6 +45,7 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true })
} catch (error) {
console.error("Notification DELETE error:", error)
return NextResponse.json({ error: "Failed to dismiss notification" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to dismiss notification"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -34,7 +34,8 @@ export async function GET() {
})
} catch (error) {
console.error("Preferences GET error:", error)
return NextResponse.json({ error: "Failed to load preferences" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load preferences"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -64,6 +65,7 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Preferences PATCH error:", error)
return NextResponse.json({ error: "Failed to save preferences" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to save preferences"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -3
View File
@@ -39,7 +39,8 @@ export async function GET() {
})
} catch (error) {
console.error("Notifications GET error:", error)
return NextResponse.json({ error: "Failed to load notifications" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load notifications"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -71,7 +72,8 @@ export async function POST(request: NextRequest) {
}, { status: 201 })
} catch (error) {
console.error("Notifications POST error:", error)
return NextResponse.json({ error: "Failed to create notification" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create notification"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -88,6 +90,7 @@ export async function PATCH() {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Notifications PATCH error:", error)
return NextResponse.json({ error: "Failed to mark all as read" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to mark all as read"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -13,6 +13,7 @@ export async function GET() {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Project statuses API error:", error)
return NextResponse.json({ error: "Failed to load statuses" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load statuses"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -38,7 +38,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json(result.rows)
} catch (error) {
console.error("Milestones API error:", error)
return NextResponse.json({ error: "Failed to load milestones" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load milestones"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -64,6 +65,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Milestones POST error:", error)
return NextResponse.json({ error: "Failed to create milestone" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create milestone"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -31,7 +31,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json(result.rows[0])
} catch (error) {
console.error("Project detail API error:", error)
return NextResponse.json({ error: "Failed to load project" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load project"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -74,6 +75,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json({ success: true, id: result.rows[0].id })
} catch (error) {
console.error("Project PATCH error:", error)
return NextResponse.json({ error: "Failed to update project" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update project"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -3
View File
@@ -49,7 +49,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Projects API error:", error)
return NextResponse.json({ error: "Failed to load projects" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load projects"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -81,7 +82,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Projects POST error:", error)
return NextResponse.json({ error: "Failed to create project" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create project"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -98,6 +100,7 @@ export async function DELETE(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Projects DELETE error:", error)
return NextResponse.json({ error: "Failed to delete project" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete project"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -11,6 +11,7 @@ export async function GET() {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Proposal statuses API error:", error)
return NextResponse.json({ error: "Failed to load statuses" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load statuses"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -31,7 +31,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Proposal items POST error:", error)
return NextResponse.json({ error: "Failed to add item" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to add item"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -49,7 +50,8 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true })
} catch (error) {
console.error("Proposal items DELETE error:", error)
return NextResponse.json({ error: "Failed to delete item" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete item"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -3
View File
@@ -47,7 +47,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
})
} catch (error) {
console.error("Proposal detail API error:", error)
return NextResponse.json({ error: "Failed to load proposal" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load proposal"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -101,7 +102,8 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json({ success: true })
} catch (error) {
console.error("Proposal PATCH error:", error)
return NextResponse.json({ error: "Failed to update proposal" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update proposal"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -113,6 +115,7 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true })
} catch (error) {
console.error("Proposal DELETE error:", error)
return NextResponse.json({ error: "Failed to delete proposal" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete proposal"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -29,6 +29,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
return NextResponse.json({ success: true, id: signature.rows[0].id })
} catch (error) {
console.error("Proposal sign error:", error)
return NextResponse.json({ error: "Failed to sign proposal" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to sign proposal"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -39,7 +39,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Proposals API error:", error)
return NextResponse.json({ error: "Failed to load proposals" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load proposals"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -80,6 +81,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, id: result.rows[0].id, proposalNumber }, { status: 201 })
} catch (error) {
console.error("Proposals POST error:", error)
return NextResponse.json({ error: "Failed to create proposal" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create proposal"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -96,6 +96,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ members, totals, period })
} catch (error) {
console.error("Resource planning API error:", error)
return NextResponse.json({ error: "Failed to load resource data" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load resource data"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -32,7 +32,8 @@ export async function GET() {
})
} catch (error) {
console.error("Company settings GET error:", error)
return NextResponse.json({ error: "Failed to load company settings" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load company settings"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -79,6 +80,7 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Company settings PATCH error:", error)
return NextResponse.json({ error: "Failed to save company settings" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to save company settings"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -56,6 +56,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
return NextResponse.json(updated.rows[0] || { success: true })
} catch (error) {
console.error("Facebook accounts PATCH error:", error)
return NextResponse.json({ error: "Failed to update Facebook account" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update Facebook account"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -33,7 +33,8 @@ export async function GET() {
return NextResponse.json(accounts.rows)
} catch (error) {
console.error("Facebook accounts GET error:", error)
return NextResponse.json({ error: "Failed to load Facebook accounts" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load Facebook accounts"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -61,6 +62,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json(result.rows[0], { status: 201 })
} catch (error) {
console.error("Facebook accounts POST error:", error)
return NextResponse.json({ error: "Failed to create Facebook account" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create Facebook account"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -36,6 +36,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Facebook scrape logs GET error:", error)
return NextResponse.json({ error: "Failed to load scrape logs" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load scrape logs"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -28,7 +28,8 @@ export async function GET() {
})
} catch (error) {
console.error("Preferences GET error:", error)
return NextResponse.json({ error: "Failed to load preferences" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load preferences"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -55,6 +56,7 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Preferences PATCH error:", error)
return NextResponse.json({ error: "Failed to save preferences" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to save preferences"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -16,7 +16,8 @@ export async function GET() {
return NextResponse.json({ websiteTheme })
} catch (error) {
console.error("Website theme GET error:", error)
return NextResponse.json({ error: "Failed to load website theme" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load website theme"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -36,6 +37,7 @@ export async function PUT(request: NextRequest) {
return NextResponse.json({ success: true, websiteTheme: theme })
} catch (error) {
console.error("Website theme PUT error:", error)
return NextResponse.json({ error: "Failed to save website theme" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to save website theme"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+4 -2
View File
@@ -25,7 +25,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Tasks POST error:", error)
return NextResponse.json({ error: "Failed to create task" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create task"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -66,6 +67,7 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Tasks PATCH error:", error)
return NextResponse.json({ error: "Failed to update task" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update task"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+6 -3
View File
@@ -44,7 +44,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json(result.rows)
} catch (error) {
console.error("Time entries API error:", error)
return NextResponse.json({ error: "Failed to load time entries" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load time entries"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -81,7 +82,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
} catch (error) {
console.error("Time entries POST error:", error)
return NextResponse.json({ error: "Failed to create time entry" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to create time entry"
return NextResponse.json({ error: message }, { status: 500 })
}
}
@@ -95,6 +97,7 @@ export async function DELETE(request: NextRequest) {
return NextResponse.json({ success: true })
} catch (error) {
console.error("Time entries DELETE error:", error)
return NextResponse.json({ error: "Failed to delete entry" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete entry"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -53,6 +53,7 @@ export async function GET() {
})
} catch (error) {
console.error("Time summary API error:", error)
return NextResponse.json({ error: "Failed to load summary" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to load summary"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -24,6 +24,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ url: `/uploads/voice/${filename}`, duration })
} catch (error) {
console.error("Voice upload error:", error)
return NextResponse.json({ error: "Upload failed" }, { status: 500 })
const message = error instanceof Error ? error.message : "Upload failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -26,6 +26,7 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
return NextResponse.json({ success: true }, { status: 200 })
} catch (error) {
console.error("Error deleting user:", error)
return NextResponse.json({ error: "Failed to delete user" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to delete user"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -35,6 +35,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ avatar })
} catch (error) {
console.error("Avatar upload error:", error)
return NextResponse.json({ error: "Failed to update avatar" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to update avatar"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -39,7 +39,8 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ users }, { status: 200 })
} catch (error) {
console.error("Error fetching users:", error)
return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 })
const message = error instanceof Error ? error.message : "Failed to fetch users"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+2 -1
View File
@@ -39,6 +39,7 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ users })
} catch (error) {
console.error("User search error:", error)
return NextResponse.json({ error: "Search failed" }, { status: 500 })
const message = error instanceof Error ? error.message : "Search failed"
return NextResponse.json({ error: message }, { status: 500 })
}
}
+3 -1
View File
@@ -33,6 +33,7 @@ import {
import { Lead, LeadStatus, User } from "@/types"
import { LEAD_SOURCES, LEAD_STATUSES } from "@/lib/constants"
import { useNotifications } from "@/providers/notification-provider"
import { toast } from "sonner"
const leadFormSchema = z.object({
companyName: z.string().min(1, "Company name is required"),
@@ -64,7 +65,7 @@ export function LeadFormDialog({ open, onOpenChange, lead, onSuccess }: LeadForm
fetch("/api/users")
.then((r) => r.json())
.then((data) => setUsers(data.users || []))
.catch(() => {})
.catch((e) => { console.error("Failed to load users", e); toast.error("Failed to load users") })
}, [])
const form = useForm<LeadFormValues>({
@@ -134,6 +135,7 @@ export function LeadFormDialog({ open, onOpenChange, lead, onSuccess }: LeadForm
onOpenChange(false)
onSuccess?.()
} catch (e) {
toast.error("Failed to save lead")
console.error("Lead save error:", e)
} finally {
setSaving(false)
@@ -6,6 +6,7 @@ import { Badge } from "@/components/ui/badge"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { ShieldAlert, RefreshCw } from "lucide-react"
import { Button } from "@/components/ui/button"
import { toast } from "sonner"
interface Account {
id: string
@@ -36,7 +37,7 @@ export function FacebookAccountsDialog({ open, onOpenChange }: { open: boolean;
if (res.ok) {
setAccounts(await res.json())
}
} catch {}
} catch (e) { console.error("Failed to load Facebook accounts", e); toast.error("Failed to load Facebook accounts") }
setLoading(false)
}
@@ -6,6 +6,7 @@ import { Input } from "@/components/ui/input"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Plus, Trash2, RefreshCw, Gauge } from "lucide-react"
import { toast } from "sonner"
interface ScoringFeature {
id: string
@@ -33,26 +34,41 @@ export function LeadScoringSettings() {
const addFeature = async () => {
if (!newFeature.featureName) return
try {
const res = await fetch("/api/leads/score/config", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newFeature),
})
if (res.ok) { setNewFeature({ featureName: "", fieldRef: "", featureType: "keyword", weight: 5 }); loadFeatures() }
} catch (e) {
console.error("Failed to add scoring feature", e)
toast.error("Failed to add scoring feature")
}
}
const deleteFeature = async (id: string) => {
try {
await fetch(`/api/leads/score/config?id=${id}`, { method: "DELETE" })
loadFeatures()
} catch (e) {
console.error("Failed to delete scoring feature", e)
toast.error("Failed to delete scoring feature")
}
}
const toggleFeature = async (f: ScoringFeature) => {
try {
await fetch("/api/leads/score/config", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id: f.id, isActive: !f.is_active }),
})
loadFeatures()
} catch (e) {
console.error("Failed to toggle scoring feature", e)
toast.error("Failed to toggle scoring feature")
}
}
const runScoring = async () => {
@@ -14,6 +14,7 @@ import {
SelectValue,
} from "@/components/ui/select"
import { Check, X, Pencil, Save } from "lucide-react"
import { toast } from "sonner"
interface FieldDef {
id: string
@@ -48,7 +49,7 @@ export function CustomFieldsSection({ entityType, customFields = {}, entityId, a
try {
const res = await fetch(`/api/custom-fields?entityType=${entityType}`)
if (res.ok) setDefinitions(await res.json())
} catch { /* ignore */ }
} catch (e) { console.error("Failed to load custom fields", e); toast.error("Failed to load custom fields") }
setLoading(false)
}, [entityType])
@@ -73,7 +74,7 @@ export function CustomFieldsSection({ entityType, customFields = {}, entityId, a
body: JSON.stringify({ customFields: values }),
})
setEditing(false)
} catch { /* ignore */ }
} catch (e) { console.error("Failed to save custom fields", e); toast.error("Failed to save custom fields") }
setSaving(false)
}