Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | 'use client'; /** * CannedResponses - Admin interface for managing canned responses */ import React, { useState, useEffect } from 'react'; import { CannedResponse } from '@/types/support'; import ResponseList from './ResponseList'; import ResponseEditor from './ResponseEditor'; export default function CannedResponses() { const [responses, setResponses] = useState<CannedResponse[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); const [editingId, setEditingId] = useState<string | null>(null); const [isCreating, setIsCreating] = useState(false); useEffect(() => { fetchResponses(); }, []); const fetchResponses = async () => { setLoading(true); setError(null); try { const response = await fetch('/api/admin/support/canned-responses'); if (!response.ok) throw new Error('Failed to fetch responses'); const data = await response.json(); setResponses(data.data || []); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setLoading(false); } }; const handleSave = async (data: Partial<CannedResponse>) => { try { const isEditing = Boolean(editingId); const url = isEditing ? `/api/admin/support/canned-responses/${editingId}` : '/api/admin/support/canned-responses'; const method = isEditing ? 'PATCH' : 'POST'; const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data)}); if (!response.ok) throw new Error('Failed to save response'); setEditingId(null); setIsCreating(false); fetchResponses(); } catch (err) { throw err; } }; const handleDelete = async (id: string) => { if (!confirm('Are you sure you want to delete this response?')) return; try { const response = await fetch(`/api/admin/support/canned-responses/${id}`, { method: 'DELETE'}); if (!response.ok) throw new Error('Failed to delete response'); fetchResponses(); } catch (err) { setError(err instanceof Error ? err.message : 'Delete failed'); } }; const handleEdit = (id: string) => { setEditingId(id); setIsCreating(false); }; const handleCreate = () => { setIsCreating(true); setEditingId(null); }; const handleCancel = () => { setEditingId(null); setIsCreating(false); }; const editingResponse = editingId ? responses.find((r) => r.id === editingId) : undefined; return ( <div className="max-w-[1170px] mx-auto px-4 sm:px-7.5 xl:px-0 space-y-6"> {/* Header */} <div className="flex items-center justify-between"> <h1 className="text-2xl font-bold text-gray-900">Canned Responses</h1> {!isCreating && !editingId && ( <button type="button" onClick={handleCreate} className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors" > Create Response </button> )} </div> {/* Error */} {error && ( <div className="bg-red-50 text-red-700 px-4 py-3 rounded-lg"> {error} </div> )} {/* Editor */} {(isCreating || editingId) && ( <ResponseEditor response={editingResponse} onSave={handleSave} onCancel={handleCancel} /> )} {/* List */} {!isCreating && !editingId && ( <ResponseList responses={responses} loading={loading} onEdit={handleEdit} onDelete={handleDelete} /> )} </div> ); } |