feat: add Mattermost bot integration and user notification configuration settings
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { getSessionUser, updateProfile, changePassword } from '@/app/actions'
|
||||
import { getSessionUser, updateProfile, changePassword, getSettings, getUserNotificationConfig, updateUserNotificationConfig } from '@/app/actions'
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from '@/components/ui/card'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
UserCircle,
|
||||
KeyRound,
|
||||
LockKeyhole,
|
||||
MessageCircle,
|
||||
} from 'lucide-react'
|
||||
|
||||
export default function ProfilePage() {
|
||||
@@ -29,6 +30,13 @@ export default function ProfilePage() {
|
||||
const [photo, setPhoto] = useState('')
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
// Notification Config state
|
||||
const [globalNotifEnabled, setGlobalNotifEnabled] = useState(false)
|
||||
const [mmChannelId, setMmChannelId] = useState('')
|
||||
const [mmActive, setMmActive] = useState(true)
|
||||
const [savingNotif, setSavingNotif] = useState(false)
|
||||
const [notifSuccess, setNotifSuccess] = useState(false)
|
||||
|
||||
// Profile state
|
||||
const [savingProfile, setSavingProfile] = useState(false)
|
||||
const [profileError, setProfileError] = useState('')
|
||||
@@ -54,6 +62,20 @@ export default function ProfilePage() {
|
||||
setUser(sessionUser)
|
||||
setName(sessionUser.name)
|
||||
setPhoto(sessionUser.photo || '')
|
||||
|
||||
const [globalSettings, notifConfig] = await Promise.all([
|
||||
getSettings(),
|
||||
getUserNotificationConfig(sessionUser.id)
|
||||
])
|
||||
|
||||
if (globalSettings?.MATTERMOST_NOTIF_ENABLED === 'true') {
|
||||
setGlobalNotifEnabled(true)
|
||||
}
|
||||
|
||||
if (notifConfig?.success && notifConfig.config) {
|
||||
setMmChannelId(notifConfig.config.mattermost_channel_id || '')
|
||||
setMmActive(notifConfig.config.is_active ?? true)
|
||||
}
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -69,14 +91,20 @@ export default function ProfilePage() {
|
||||
setProfileSuccess(false)
|
||||
setSavingProfile(true)
|
||||
|
||||
const res = await updateProfile(user.id, name.trim(), photo.trim() || null)
|
||||
const [res, notifRes] = await Promise.all([
|
||||
updateProfile(user.id, name.trim(), photo.trim() || null),
|
||||
globalNotifEnabled ? updateUserNotificationConfig(user.id, {
|
||||
mattermost_channel_id: mmChannelId,
|
||||
is_active: mmActive
|
||||
}) : Promise.resolve({ success: true, error: null })
|
||||
])
|
||||
|
||||
if (res.success) {
|
||||
if (res.success && notifRes.success) {
|
||||
setUser(res.user)
|
||||
setProfileSuccess(true)
|
||||
setTimeout(() => setProfileSuccess(false), 3000)
|
||||
} else {
|
||||
setProfileError(res.error || 'Terjadi kesalahan')
|
||||
setProfileError(res.error || notifRes.error || 'Terjadi kesalahan')
|
||||
}
|
||||
setSavingProfile(false)
|
||||
}
|
||||
@@ -215,6 +243,55 @@ export default function ProfilePage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{globalNotifEnabled && (
|
||||
<div className="space-y-6 pt-6 mt-6 border-t border-slate-100 dark:border-slate-800">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-purple-100 text-purple-600 dark:bg-purple-900/30 dark:text-purple-400">
|
||||
<MessageCircle className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-bold text-slate-900 dark:text-white">
|
||||
Notifikasi Mattermost
|
||||
</h3>
|
||||
<p className="mt-0.5 text-[11px] text-slate-500">
|
||||
Terima update pesanan PO langsung di DM Mattermost Anda.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row items-start space-x-3 space-y-0 rounded-md border border-slate-200 p-4 dark:border-slate-800">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="mmActive"
|
||||
checked={mmActive}
|
||||
onChange={(e) => setMmActive(e.target.checked)}
|
||||
className="mt-1 h-4 w-4 rounded border-slate-300 text-[#1B2CC1] focus:ring-[#1B2CC1]"
|
||||
/>
|
||||
<div className="space-y-1 leading-none">
|
||||
<Label htmlFor="mmActive" className="text-sm font-bold">
|
||||
Aktifkan Notifikasi
|
||||
</Label>
|
||||
<p className="text-[11px] text-slate-500">
|
||||
Kirim notifikasi setiap kali ada yang merubah pesanannya di PO Anda.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="mm-channel" className="text-xs font-bold tracking-wider text-slate-700 uppercase dark:text-slate-300">
|
||||
Username / Channel ID
|
||||
</Label>
|
||||
<Input
|
||||
id="mm-channel"
|
||||
value={mmChannelId}
|
||||
onChange={(e) => setMmChannelId(e.target.value)}
|
||||
placeholder="Contoh: @firman atau 9dpxnitm..."
|
||||
className="h-11 rounded-xl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{profileError && (
|
||||
<div className="rounded-xl bg-red-50 p-3 text-xs font-semibold text-red-600">
|
||||
{profileError}
|
||||
@@ -223,7 +300,7 @@ export default function ProfilePage() {
|
||||
{profileSuccess && (
|
||||
<div className="flex items-center gap-2 rounded-xl bg-emerald-50 p-3 text-xs font-bold text-emerald-700">
|
||||
<CheckCircle className="h-4 w-4" />
|
||||
<span>Profil berhasil diperbarui!</span>
|
||||
<span>Perubahan berhasil disimpan!</span>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
@@ -244,6 +321,7 @@ export default function ProfilePage() {
|
||||
</div>
|
||||
</form>
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Right 1 Col: Account Details */}
|
||||
|
||||
Reference in New Issue
Block a user