diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
| commit | e0dfb55c5457aec489fc084c4567e791b4c65eb1 (patch) | |
| tree | 68543a65d88f5afb3a0202925804103daa91bc6f /components/faq/FaqManager.tsx | |
3/25 까지의 대표님 작업사항
Diffstat (limited to 'components/faq/FaqManager.tsx')
| -rw-r--r-- | components/faq/FaqManager.tsx | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/components/faq/FaqManager.tsx b/components/faq/FaqManager.tsx new file mode 100644 index 00000000..27755270 --- /dev/null +++ b/components/faq/FaqManager.tsx @@ -0,0 +1,192 @@ +'use client';
+
+import { useState } from 'react';
+import { FaqCategory } from './FaqCard';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent } from '@/components/ui/card';
+import { Input } from '@/components/ui/input';
+import { Textarea } from '@/components/ui/textarea';
+import { Plus, Trash, Save, Settings } from 'lucide-react';
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
+import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
+import { useRouter } from 'next/navigation';
+
+interface FaqManagerProps {
+ initialData: FaqCategory[];
+ onSave: (data: FaqCategory[]) => Promise<void>;
+ lng: string;
+}
+
+export function FaqManager({ initialData, onSave, lng }: FaqManagerProps) {
+ const [categories, setCategories] = useState<FaqCategory[]>(initialData);
+ const [activeTab, setActiveTab] = useState<string>(categories[0]?.label || '');
+ const [isSettingsView, setIsSettingsView] = useState(false);
+ const [showSaveDialog, setShowSaveDialog] = useState(false);
+ const router = useRouter();
+
+ const addCategory = () => {
+ const newCategory = {
+ label: 'New Category',
+ items: []
+ };
+ setCategories([...categories, newCategory]);
+ setActiveTab(newCategory.label);
+ };
+
+ const addItem = (categoryIndex: number) => {
+ const newCategories = [...categories];
+ newCategories[categoryIndex].items.push({
+ title: 'New FAQ Item',
+ content: ['Enter content here']
+ });
+ setCategories(newCategories);
+ };
+
+ const handleSave = async () => {
+ await onSave(categories);
+ setShowSaveDialog(false);
+ router.push(`/${lng}/evcp/faq`);
+ };
+
+ const updateCategory = (index: number, label: string) => {
+ const newCategories = [...categories];
+ newCategories[index] = { ...newCategories[index], label };
+ setCategories(newCategories);
+ if (activeTab === categories[index].label) {
+ setActiveTab(label);
+ }
+ };
+
+ const updateItem = (categoryIndex: number, itemIndex: number, field: 'title' | 'content', value: string | string[]) => {
+ const newCategories = [...categories];
+ if (field === 'content') {
+ newCategories[categoryIndex].items[itemIndex][field] = (value as string).split('\n');
+ } else {
+ newCategories[categoryIndex].items[itemIndex][field] = value as string;
+ }
+ setCategories(newCategories);
+ };
+
+ const removeCategory = (index: number) => {
+ const newCategories = categories.filter((_, i) => i !== index);
+ setCategories(newCategories);
+ setActiveTab(newCategories[0]?.label || '');
+ };
+
+ const removeItem = (categoryIndex: number, itemIndex: number) => {
+ const newCategories = [...categories];
+ newCategories[categoryIndex].items = newCategories[categoryIndex].items.filter((_, i) => i !== itemIndex);
+ setCategories(newCategories);
+ };
+
+ return (
+ <div className="space-y-6">
+ <div className="flex justify-between items-center">
+ <div className="flex items-center space-x-2">
+ <Button
+ variant={isSettingsView ? "default" : "outline"}
+ onClick={() => setIsSettingsView(true)}
+ >
+ <Settings className="w-4 h-4 mr-2" />
+ Category Settings
+ </Button>
+ <Button
+ variant={!isSettingsView ? "default" : "outline"}
+ onClick={() => setIsSettingsView(false)}
+ >
+ FAQ Management
+ </Button>
+ </div>
+ <Button onClick={() => setShowSaveDialog(true)}>
+ <Save className="w-4 h-4 mr-2" />
+ Save Changes
+ </Button>
+ </div>
+
+ {isSettingsView ? (
+ <div className="grid gap-4">
+ {categories.map((category, index) => (
+ <Card key={index} className="p-4">
+ <div className="flex space-x-4 items-center">
+ <Input
+ value={category.label}
+ onChange={(e) => updateCategory(index, e.target.value)}
+ className="flex-1"
+ placeholder="Category Name"
+ />
+ <Button variant="destructive" size="icon" onClick={() => removeCategory(index)}>
+ <Trash className="w-4 h-4" />
+ </Button>
+ </div>
+ </Card>
+ ))}
+ <Button onClick={addCategory} variant="outline" className="w-full">
+ <Plus className="w-4 h-4 mr-2" />
+ Add Category
+ </Button>
+ </div>
+ ) : (
+ <Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-4">
+ <TabsList>
+ {categories.map((category) => (
+ <TabsTrigger key={category.label} value={category.label}>
+ {category.label}
+ </TabsTrigger>
+ ))}
+ </TabsList>
+
+ {categories.map((category, categoryIndex) => (
+ <TabsContent key={category.label} value={category.label} className="space-y-4">
+ {category.items.map((item, itemIndex) => (
+ <Card key={itemIndex}>
+ <CardContent className="space-y-2 pt-6">
+ <div className="flex justify-between items-start">
+ <Input
+ value={item.title}
+ onChange={(e) => updateItem(categoryIndex, itemIndex, 'title', e.target.value)}
+ className="flex-1 mr-2"
+ placeholder="Question"
+ />
+ <Button variant="destructive" size="icon" onClick={() => removeItem(categoryIndex, itemIndex)}>
+ <Trash className="w-4 h-4" />
+ </Button>
+ </div>
+ <Textarea
+ value={item.content.join('\n')}
+ onChange={(e) => updateItem(categoryIndex, itemIndex, 'content', e.target.value)}
+ placeholder="Answer (separate lines with Enter)"
+ rows={3}
+ />
+ </CardContent>
+ </Card>
+ ))}
+ <Button variant="outline" onClick={() => addItem(categoryIndex)} className="w-full">
+ <Plus className="w-4 h-4 mr-2" />
+ Add FAQ Item
+ </Button>
+ </TabsContent>
+ ))}
+ </Tabs>
+ )}
+
+ <Dialog open={showSaveDialog} onOpenChange={setShowSaveDialog}>
+ <DialogContent>
+ <DialogHeader>
+ <DialogTitle>Save Changes</DialogTitle>
+ <DialogDescription>
+ Are you sure you want to save the changes? This will update the FAQ data.
+ </DialogDescription>
+ </DialogHeader>
+ <DialogFooter>
+ <Button variant="outline" onClick={() => setShowSaveDialog(false)}>
+ Cancel
+ </Button>
+ <Button onClick={handleSave}>
+ Save
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ </div>
+ );
+}
\ No newline at end of file |
