feat: implement Sonner notifications, add Setting model, and reorganize user management into settings navigation.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { getSettings, updateSettings } from '@/app/actions'
|
||||
import { toast } from 'sonner'
|
||||
import { Loader2, Save, MessageSquare, MessageCircle, AlertCircle } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
|
||||
export default function IntegrationsPage() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [settings, setSettings] = useState({
|
||||
MATTERMOST_WEBHOOK_URL: '',
|
||||
MATTERMOST_TEMPLATE: '',
|
||||
WHATSAPP_TEMPLATE: ''
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSettings = async () => {
|
||||
const data = await getSettings()
|
||||
if (data) {
|
||||
setSettings({
|
||||
MATTERMOST_WEBHOOK_URL: data.MATTERMOST_WEBHOOK_URL || '',
|
||||
MATTERMOST_TEMPLATE: data.MATTERMOST_TEMPLATE || 'Halo tim! Lagi ada orderan open nih untuk {title}. Mumpung belum di-checkout, yang mau ikutan nitip bisa langsung cek ke sini ya: {url}',
|
||||
WHATSAPP_TEMPLATE: data.WHATSAPP_TEMPLATE || 'Halo tim! Lagi ada orderan open nih untuk {title}. Mumpung belum di-checkout, yang mau ikutan nitip bisa langsung cek ke sini ya: {url}'
|
||||
})
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
fetchSettings()
|
||||
}, [])
|
||||
|
||||
const handleChange = (key: string, value: string) => {
|
||||
setSettings(prev => ({ ...prev, [key]: value }))
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
setSaving(true)
|
||||
const res = await updateSettings(settings)
|
||||
if (res.success) {
|
||||
toast.success('Berhasil Disimpan', {
|
||||
description: 'Pengaturan integrasi berhasil disimpan!',
|
||||
duration: 3000
|
||||
})
|
||||
} else {
|
||||
toast.error('Gagal', {
|
||||
description: 'Gagal menyimpan pengaturan',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
setSaving(false)
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex justify-center items-center h-64">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-[#1B2CC1]" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-8">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-slate-900 dark:text-white">Integrasi & Sharing</h2>
|
||||
<p className="text-xs text-slate-500 mt-1">Konfigurasi endpoint API dan template pesan otomatis.</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 max-w-3xl">
|
||||
{/* Mattermost Section */}
|
||||
<div className="p-5 rounded-2xl border border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 space-y-4">
|
||||
<div className="flex items-center gap-2 text-indigo-600 dark:text-indigo-400 font-black">
|
||||
<MessageSquare className="w-5 h-5" />
|
||||
<h3>Mattermost Webhook</h3>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">Gunakan URL Incoming Webhook dari Mattermost untuk mengirim broadcast PO baru secara otomatis.</p>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs font-bold uppercase text-slate-700">Webhook URL</Label>
|
||||
<Input
|
||||
value={settings.MATTERMOST_WEBHOOK_URL}
|
||||
onChange={e => handleChange('MATTERMOST_WEBHOOK_URL', e.target.value)}
|
||||
className="h-11 rounded-xl bg-white dark:bg-slate-950"
|
||||
placeholder="https://mattermost.yourdomain.com/hooks/xxx"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs font-bold uppercase text-slate-700">Pesan Template</Label>
|
||||
<Textarea
|
||||
value={settings.MATTERMOST_TEMPLATE}
|
||||
onChange={e => handleChange('MATTERMOST_TEMPLATE', e.target.value)}
|
||||
className="rounded-xl min-h-[100px] bg-white dark:bg-slate-950"
|
||||
placeholder="Template pesan..."
|
||||
/>
|
||||
<p className="text-[10px] text-slate-500 flex items-center gap-1"><AlertCircle className="w-3 h-3"/> Gunakan variabel: {'{title}'}, {'{url}'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* WhatsApp Section */}
|
||||
<div className="p-5 rounded-2xl border border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50 space-y-4">
|
||||
<div className="flex items-center gap-2 text-emerald-600 dark:text-emerald-400 font-black">
|
||||
<MessageCircle className="w-5 h-5" />
|
||||
<h3>WhatsApp Share Template</h3>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">Atur template teks default saat user menekan tombol share ke WhatsApp.</p>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs font-bold uppercase text-slate-700">Pesan Template</Label>
|
||||
<Textarea
|
||||
value={settings.WHATSAPP_TEMPLATE}
|
||||
onChange={e => handleChange('WHATSAPP_TEMPLATE', e.target.value)}
|
||||
className="rounded-xl min-h-[100px] bg-white dark:bg-slate-950"
|
||||
placeholder="Template pesan..."
|
||||
/>
|
||||
<p className="text-[10px] text-slate-500 flex items-center gap-1"><AlertCircle className="w-3 h-3"/> Gunakan variabel: {'{title}'}, {'{url}'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pt-2">
|
||||
<Button onClick={handleSave} disabled={saving} className="bg-[#1B2CC1] hover:bg-[#15229E] text-white rounded-xl h-11 px-8 font-bold shadow-md w-full sm:w-auto">
|
||||
{saving ? <Loader2 className="w-4 h-4 animate-spin mr-2" /> : <Save className="w-4 h-4 mr-2" />}
|
||||
Simpan Konfigurasi
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user