1+ 'use client'
2+ import Navbar from "@/components/dashboard/navbar"
3+ import Sidebar from "@/components/dashboard/sidebar"
4+ import { useSidebar } from "@/context/userSidebar" ;
5+ import { LogOut , LayoutDashboard , Trash2 } from "lucide-react"
6+ import Page from "@/components/dashboard/server/page" ;
7+ import JoinsAndLeaves from "@/components/dashboard/server/joinandleaves" ;
8+ import Messages from "@/components/dashboard/server/messages" ;
9+ import Link from "next/link" ;
10+ import { useState , useEffect } from "react" ;
11+ import AuditLogsTable from "@/components/dashboard/server/home_log" ;
12+ import { motion , AnimatePresence } from "framer-motion" ;
13+ import { HexColorPicker } from "react-colorful" ;
14+ import { useRouter } from "next/navigation" ;
15+
16+ export default function Dashboard ( ) {
17+
18+ const [ isOpen , setIsOpen ] = useState ( false ) ;
19+ const [ openColorPicker , setOpenColorPicker ] = useState ( null ) ;
20+ const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
21+ const router = useRouter ( ) ;
22+
23+ const logTypes = [
24+ 'Server Updates Log' ,
25+ 'Member Roles Updated' ,
26+ 'Nickname Changed' ,
27+ 'Timeout' ,
28+ 'Member Banned' ,
29+ 'Member Unbanned' ,
30+ 'Member Kicked' ,
31+ 'Role Created' ,
32+ 'Role Updated' ,
33+ 'Role Deleted' ,
34+ 'Channel Created' ,
35+ 'Channel Updated' ,
36+ 'Channel Deleted' ,
37+ 'Message Deleted' ,
38+ 'Message Updated' ,
39+ 'Media Log' ,
40+ 'Member Joined Voice' ,
41+ 'Member Left Voice' ,
42+ 'Member Voice Muted/Unmuted' ,
43+ 'Member Voice Deafened/Undeafened' ,
44+ 'Emoji Created' ,
45+ 'Emoji Deleted' ,
46+ 'Sticker Created' ,
47+ 'Sticker Deleted'
48+ ] ;
49+
50+ // State for each log type
51+ const [ logSettings , setLogSettings ] = useState (
52+ logTypes . reduce ( ( acc , logName ) => {
53+ acc [ logName ] = {
54+ enabled : false ,
55+ channel : null ,
56+ color : "#3357FF"
57+ } ;
58+ return acc ;
59+ } , { } )
60+ ) ;
61+
62+ const handleToggle = ( logName ) => {
63+ setLogSettings ( prev => ( {
64+ ...prev ,
65+ [ logName ] : {
66+ ...prev [ logName ] ,
67+ enabled : ! prev [ logName ] . enabled
68+ }
69+ } ) ) ;
70+ console . log ( `${ logName } is now ${ ! logSettings [ logName ] . enabled ? 'enabled' : 'disabled' } ` ) ;
71+ } ;
72+
73+ const handleColorChange = ( logName , newColor ) => {
74+ setLogSettings ( prev => ( {
75+ ...prev ,
76+ [ logName ] : {
77+ ...prev [ logName ] ,
78+ color : newColor
79+ }
80+ } ) ) ;
81+ console . log ( `${ logName } color changed to ${ newColor } ` ) ;
82+ } ;
83+
84+ const addCommas = ( num ) => {
85+ return num . toString ( ) . replace ( / \B (? = ( \d { 3 } ) + (? ! \d ) ) / g, "," ) ;
86+ } ;
87+
88+ // Filter logs based on search query
89+ const filteredLogTypes = logTypes . filter ( logName =>
90+ logName . toLowerCase ( ) . includes ( searchQuery . toLowerCase ( ) )
91+ ) ;
92+
93+
94+ function darken ( hex , amount = 20 ) {
95+ let col = hex . replace ( '#' , '' )
96+ if ( col . length === 3 )
97+ col = col . split ( '' ) . map ( c => c + c ) . join ( '' )
98+ const num = parseInt ( col , 16 )
99+ let r = ( num >> 16 ) - amount
100+ let g = ( ( num >> 8 ) & 0x00ff ) - amount
101+ let b = ( num & 0x0000ff ) - amount
102+ r = r < 0 ? 0 : r
103+ g = g < 0 ? 0 : g
104+ b = b < 0 ? 0 : b
105+ return `#${ ( r << 16 | g << 8 | b ) . toString ( 16 ) . padStart ( 6 , '0' ) } `
106+ }
107+
108+ const formatted = addCommas ( "1250000" )
109+
110+ return (
111+ < >
112+
113+ < div className = "flex flex-col md:flex-row md:items-center gap-1 md:gap-4 mb-4" >
114+ < h2 className = "text-white flex space-x-2 font-medium text-lg md:text-xl" >
115+ < svg xmlns = "http://www.w3.org/2000/svg" width = { 24 } height = { 24 } className = "w-7.5 h-6.5" viewBox = "0 0 24 24" >
116+ < path fill = "currentColor" d = "M11.11 4.049a1 1 0 1 0-.22-1.988C5.888 2.614 2 6.852 2 12c0 5.523 4.477 10 10 10c5.146 0 9.383-3.887 9.939-8.885a1 1 0 0 0-1.988-.221A8.001 8.001 0 0 1 4 12a8 8 0 0 1 7.11-7.951m3.657-1.658a1 1 0 0 0-.54 1.925q.432.122.842.29a1 1 0 0 0 .757-1.852a10 10 0 0 0-1.059-.363m2.582 2.3a1 1 0 0 1 1.413-.06q.318.291.609.608a1 1 0 0 1-1.474 1.352a8 8 0 0 0-.486-.486a1 1 0 0 1-.062-1.413M11 6a1 1 0 0 1 1 1v5h3a1 1 0 1 1 0 2h-4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1m8.94 1.623a1 1 0 0 1 1.304.547a10 10 0 0 1 .365 1.063a1 1 0 1 1-1.925.54a8 8 0 0 0-.291-.846a1 1 0 0 1 .546-1.304" > </ path >
117+ </ svg >
118+ < span > Audit Logs</ span >
119+ </ h2 >
120+
121+ </ div >
122+ < hr className = "border-[#302e46] mb-4" />
123+
124+
125+
126+ < div className = "flex flex-row-reverse items-center w-full bg-[#191822]/60 px-4 py-2 border-2 border-[#222031] rounded-md transition-colors focus-within:border-[#2e2b41]" >
127+ < input
128+ placeholder = "Search for log name"
129+ value = { searchQuery }
130+ onChange = { ( e ) => setSearchQuery ( e . target . value ) }
131+ className = "w-full bg-transparent items-center mt-1 placeholder:text-[#928ea8] outline-none text-white"
132+ />
133+ < svg
134+ xmlns = "http://www.w3.org/2000/svg"
135+ width = { 30 }
136+ height = { 30 }
137+ viewBox = "0 0 24 24"
138+ className = " mr-2 text-[#928ea8]"
139+ >
140+ < g fill = "none" >
141+ < path
142+ stroke = "currentColor"
143+ strokeLinecap = "round"
144+ strokeLinejoin = "round"
145+ strokeMiterlimit = { 10 }
146+ strokeWidth = { 1.5 }
147+ d = "m21 21l-4-4m2-6a8 8 0 1 1-16 0a8 8 0 0 1 16 0m-8.194-2.224l-.377 1.508a.2.2 0 0 1-.145.145l-1.508.377c-.202.05-.202.338 0 .388l1.508.377a.2.2 0 0 1 .145.145l.377 1.508c.05.202.338.202.388 0l.377-1.508a.2.2 0 0 1 .145-.145l1.508-.377c.202-.05.202-.338 0-.388l-1.508-.377a.2.2 0 0 1-.145-.145l-.377-1.508c-.05-.202-.338-.202-.388 0"
148+ />
149+ < path
150+ fill = "currentColor"
151+ fillOpacity = { 0.16 }
152+ d = "M11 19a8 8 0 1 0 0-16a8 8 0 0 0 0 16"
153+ />
154+ </ g >
155+ </ svg >
156+ </ div >
157+
158+ < div className = "mt-[2rem] grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 xl:grid-cols-3 gap-4 mb-[2rem]" >
159+ { filteredLogTypes . length > 0 ? (
160+ filteredLogTypes . map ( ( logName , index ) => (
161+ < div key = { index } className = "bg-[#191822]/50 p-4 rounded-xl border border-[#2e2b41]" >
162+ < div className = "flex justify-between" >
163+
164+ < div className = "flex space-x-2 items-center" >
165+ < div className = "" >
166+ < span className = "text-lg uppercase " > { logName } </ span >
167+ </ div >
168+
169+ </ div >
170+ < label className = "relative inline-flex items-center cursor-pointer" >
171+ < input
172+ type = "checkbox"
173+ checked = { logSettings [ logName ] . enabled }
174+ onChange = { ( ) => handleToggle ( logName ) }
175+ className = "sr-only peer"
176+ />
177+ < div className = "w-16 h-8 bg-[#22202e] rounded-full peer-checked:bg-indigo-500 transition-colors" > </ div >
178+ < div className = "absolute left-1 w-6 h-6 bg-white rounded-full peer-checked:translate-x-8 transition-transform" > </ div >
179+ </ label >
180+ </ div >
181+ < hr className = "border-[#302e46] mt-4 mb-4" />
182+ < div className = "" >
183+ < span className = "text-[#d2cbf1] manrope" > Channel</ span >
184+ < motion . button
185+ className = "cursor-pointer bg-[#191822]/50 px-4 py-3 border border-[#222031] rounded-md justify-between flex w-full transition-colors"
186+ >
187+ < div className = "flex space-x-2 items-center text-center select-none" >
188+ Choose
189+ </ div >
190+ < motion . svg
191+ xmlns = "http://www.w3.org/2000/svg"
192+ className = "rotate-90"
193+ width = { 20 }
194+ height = { 20 }
195+ viewBox = "0 0 20 20"
196+ transition = { { duration : 0.3 } }
197+ >
198+ < path
199+ fill = "currentColor"
200+ fillRule = "evenodd"
201+ d = "M16.53 10.511a.75.75 0 0 0 0-1.06l-3.25-3.25a.75.75 0 0 0-1.06 1.06l2.72 2.72l-2.72 2.72a.75.75 0 1 0 1.06 1.06zm-9.81-4.31l-3.25 3.25a.75.75 0 0 0 0 1.06l3.25 3.25a.75.75 0 1 0 1.06-1.06l-2.72-2.72l2.72-2.72a.75.75 0 0 0-1.06-1.06"
202+ clipRule = "evenodd"
203+ />
204+ </ motion . svg >
205+ </ motion . button >
206+ </ div >
207+
208+ < div className = "relative mt-4" >
209+ < label className = "block text-[#d2cbf1] manrope mb-2" > Color</ label >
210+ < div className = "flex items-center gap-2" >
211+ < button
212+ onClick = { ( ) => setOpenColorPicker ( openColorPicker === logName ? null : logName ) }
213+ className = "h-12 w-full rounded-md cursor-pointer"
214+ style = { { backgroundColor : logSettings [ logName ] . color } }
215+ />
216+
217+ </ div >
218+ { openColorPicker === logName && (
219+ < >
220+ < motion . div
221+ className = "fixed inset-0 z-40"
222+ initial = { { opacity : 0 } }
223+ animate = { { opacity : 1 } }
224+ exit = { { opacity : 0 } }
225+ onClick = { ( ) => setOpenColorPicker ( null ) }
226+ />
227+ < motion . div
228+ className = "absolute z-[9999] "
229+ initial = { { opacity : 0 , scale : 0.95 , y : - 10 } }
230+ animate = { { opacity : 1 , scale : 1 , y : 0 } }
231+ exit = { { opacity : 0 , scale : 0.95 , y : - 10 } }
232+ transition = { { duration : 0.2 } }
233+ >
234+ < div className = "bg-[#201f29] p-3 px-4 rounded-lg border border-[#2e2b41] shadow-lg" >
235+ < span className = "text-[#a29dbb] text-sm mb-2 block" > Color Picker</ span >
236+ < HexColorPicker
237+ color = { logSettings [ logName ] . color }
238+ onChange = { ( newColor ) => handleColorChange ( logName , newColor ) }
239+ style = { { width : '220px' , height : '160px' } }
240+ />
241+ < div className = "mt-4 flex items-center gap-2" >
242+ < div
243+ className = "p-5 rounded-lg border"
244+ style = { {
245+ backgroundColor : logSettings [ logName ] . color ,
246+ borderColor : darken ( logSettings [ logName ] . color , 10 ) ,
247+ } }
248+ />
249+ < input
250+ value = { logSettings [ logName ] . color }
251+ onChange = { ( e ) => handleColorChange ( logName , e . target . value ) }
252+ className = "p-2 rounded-lg focus:outline-none border border-[#3a394b] bg-[#31303f] w-[170px]"
253+ />
254+ </ div >
255+ </ div >
256+ </ motion . div >
257+ </ >
258+ ) }
259+ </ div >
260+
261+
262+ </ div >
263+ ) )
264+ ) : (
265+ < div className = "col-span-full text-center py-12" >
266+ < div className = "flex flex-col items-center gap-3" >
267+ < svg xmlns = "http://www.w3.org/2000/svg" width = { 48 } height = { 48 } viewBox = "0 0 24 24" className = "text-[#928ea8]" >
268+ < g fill = "none" >
269+ < path stroke = "currentColor" strokeLinecap = "round" strokeLinejoin = "round" strokeMiterlimit = { 10 } strokeWidth = { 1.5 } d = "m21 21l-4-4m2-6a8 8 0 1 1-16 0a8 8 0 0 1 16 0" />
270+ < path fill = "currentColor" fillOpacity = { 0.16 } d = "M11 19a8 8 0 1 0 0-16a8 8 0 0 0 0 16" />
271+ </ g >
272+ </ svg >
273+ < p className = "text-[#928ea8] text-lg" > No logs found matching "{ searchQuery } "</ p >
274+ </ div >
275+ </ div >
276+ ) }
277+
278+ </ div >
279+
280+ </ >
281+
282+ )
283+ }
0 commit comments