Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'warn',
},
}
34 changes: 17 additions & 17 deletions dist/assets/index-RpkfYM5z.js → dist/assets/index-D3cSeV7q.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CrestChat - Discord Clone</title>
<script type="module" crossorigin src="/assets/index-RpkfYM5z.js"></script>
<script type="module" crossorigin src="/assets/index-D3cSeV7q.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Bv16ervk.css">
</head>
<body>
Expand Down
6 changes: 3 additions & 3 deletions src/components/ChatArea.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useState, useRef, useEffect } from 'react'
import { useMessages } from '../hooks/useMessages'
import { Channel } from '../integrations/supabase/types'
import { Channel, Server, Message } from '../integrations/supabase/types'
import { toast } from 'sonner'

interface ChatAreaProps {
channel: Channel
server?: any
server?: Server
onServerUpdate: () => void
onChannelUpdate: () => void
onOpenServerSettings?: () => void
Expand Down Expand Up @@ -90,7 +90,7 @@ export default function ChatArea({ channel, server, onOpenServerSettings }: Chat
}
}

const startEditing = (message: any) => {
const startEditing = (message: Message) => {
setEditingMessageId(message.id)
setEditContent(message.content)
}
Expand Down
23 changes: 12 additions & 11 deletions src/components/OnlineUsers.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useCallback } from 'react'
import { supabase } from '../integrations/supabase/client'
import { Server } from '../integrations/supabase/types'

Expand All @@ -18,13 +18,7 @@ export default function OnlineUsers({ server }: OnlineUsersProps) {
const [onlineUsers, setOnlineUsers] = useState<OnlineUser[]>([])
const [loading, setLoading] = useState(false)

useEffect(() => {
if (server) {
loadOnlineUsers()
}
}, [server])

const loadOnlineUsers = async () => {
const loadOnlineUsers = useCallback(async () => {
if (!server) return
setLoading(true)
try {
Expand All @@ -46,8 +40,9 @@ export default function OnlineUsers({ server }: OnlineUsersProps) {

const users = data
?.map(item => item.user)
.filter((user: any) => user && user.status !== 'offline')
.sort((a: any, b: any) => {
.flat()
.filter((user) => user && user.status !== 'offline')
.sort((a, b) => {
// Sort by status priority: online > idle > dnd > invisible
const statusOrder = { online: 0, idle: 1, dnd: 2, invisible: 3 }
return statusOrder[a.status as keyof typeof statusOrder] - statusOrder[b.status as keyof typeof statusOrder]
Expand All @@ -59,7 +54,13 @@ export default function OnlineUsers({ server }: OnlineUsersProps) {
} finally {
setLoading(false)
}
}
}, [server])

useEffect(() => {
if (server) {
loadOnlineUsers()
}
}, [server, loadOnlineUsers])

const getStatusColor = (status: string) => {
switch (status) {
Expand Down
64 changes: 36 additions & 28 deletions src/components/ServerSettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useCallback } from 'react'
import { supabase } from '../integrations/supabase/client'
import { Server, Channel } from '../integrations/supabase/types'
import { Server, Channel, ServerMember } from '../integrations/supabase/types'
import { toast } from 'sonner'

interface ServerSettingsModalProps {
Expand All @@ -21,7 +21,7 @@ export default function ServerSettingsModal({
const [activeTab, setActiveTab] = useState('overview')
const [loading, setLoading] = useState(false)
const [channels, setChannels] = useState<Channel[]>([])
const [members, setMembers] = useState<any[]>([])
const [members, setMembers] = useState<ServerMember[]>([])
const [loadingMembers, setLoadingMembers] = useState(false)
const [serverForm, setServerForm] = useState({
name: '',
Expand All @@ -30,19 +30,7 @@ export default function ServerSettingsModal({
})
const [newChannelName, setNewChannelName] = useState('')

useEffect(() => {
if (server && isOpen) {
setServerForm({
name: server.name,
description: server.description || '',
privacyLevel: server.privacy_level
})
loadChannels()
loadMembers()
}
}, [server, isOpen])

const loadChannels = async () => {
const loadChannels = useCallback(async () => {
if (!server) return
try {
const { data, error } = await supabase
Expand All @@ -57,9 +45,9 @@ export default function ServerSettingsModal({
console.error('Error loading channels:', error)
toast.error('Failed to load channels')
}
}
}, [server])

const loadMembers = async () => {
const loadMembers = useCallback(async () => {
if (!server) return
setLoadingMembers(true)
try {
Expand All @@ -85,14 +73,34 @@ export default function ServerSettingsModal({
}

console.log('Members loaded successfully:', data)
setMembers(data || [])
const formattedMembers: ServerMember[] = (data || []).map((item: any) => ({
id: item.user_id,
server_id: server.id,
user_id: item.user_id,
role: 'member',
joined_at: new Date().toISOString(),
user: Array.isArray(item.user) ? item.user[0] : item.user
}))
setMembers(formattedMembers)
} catch (error) {
console.error('Error loading members:', error)
toast.error('Failed to load members')
} finally {
setLoadingMembers(false)
}
}
}, [server])

useEffect(() => {
if (server && isOpen) {
setServerForm({
name: server.name,
description: server.description || '',
privacyLevel: server.privacy_level
})
loadChannels()
loadMembers()
}
}, [server, isOpen, loadChannels, loadMembers])

const handleSaveServer = async () => {
if (!server) return
Expand All @@ -110,8 +118,8 @@ export default function ServerSettingsModal({
if (error) throw error
toast.success('Server updated successfully!')
onServerUpdate()
} catch (error: any) {
toast.error(`Failed to update server: ${error.message}`)
} catch (error) {
toast.error(`Failed to update server: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand All @@ -133,8 +141,8 @@ export default function ServerSettingsModal({
setNewChannelName('')
loadChannels()
onChannelUpdate()
} catch (error: any) {
toast.error(`Failed to create channel: ${error.message}`)
} catch (error) {
toast.error(`Failed to create channel: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}

Expand All @@ -150,8 +158,8 @@ export default function ServerSettingsModal({
toast.success('Channel deleted successfully!')
loadChannels()
onChannelUpdate()
} catch (error: any) {
toast.error(`Failed to delete channel: ${error.message}`)
} catch (error) {
toast.error(`Failed to delete channel: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}

Expand All @@ -167,8 +175,8 @@ export default function ServerSettingsModal({
if (error) throw error
toast.success('Member removed successfully!')
loadMembers()
} catch (error: any) {
toast.error(`Failed to remove member: ${error.message}`)
} catch (error) {
toast.error(`Failed to remove member: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}

Expand Down
26 changes: 18 additions & 8 deletions src/components/ServerSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import { Server, Channel } from '../integrations/supabase/types'
import { supabase } from '../integrations/supabase/client'
import { toast } from 'sonner'

interface AuthUser {
id: string
email: string
username: string
display_name: string
avatar_url?: string
status: string
created_at: string
}

interface ServerSidebarProps {
servers: Server[]
currentServer: Server | null
currentChannel: Channel | null
onServerSelect: (server: Server) => void
onChannelSelect: (channel: Channel) => void
user: any
user: AuthUser
}

export default function ServerSidebar({
Expand Down Expand Up @@ -100,9 +110,9 @@ export default function ServerSidebar({

// Refresh the page to show new server
window.location.reload()
} catch (error: any) {
} catch (error) {
console.error('Full error:', error)
toast.error(`Failed to create server: ${error.message}`)
toast.error(`Failed to create server: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand Down Expand Up @@ -132,8 +142,8 @@ export default function ServerSidebar({

// Refresh the page to show new channel
window.location.reload()
} catch (error: any) {
toast.error(`Failed to create channel: ${error.message}`)
} catch (error) {
toast.error(`Failed to create channel: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand All @@ -159,8 +169,8 @@ export default function ServerSidebar({

// Refresh the page to show new server
window.location.reload()
} catch (error: any) {
toast.error(`Failed to join server: ${error.message}`)
} catch (error) {
toast.error(`Failed to join server: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand All @@ -181,7 +191,7 @@ export default function ServerSidebar({
<div className="flex-1 overflow-y-auto p-4 space-y-2">
{/* Home Button */}
<button
onClick={() => onServerSelect(null as any)}
onClick={() => onServerSelect(null as unknown as Server)}
className={`w-full p-3 rounded-lg transition-colors ${
!currentServer
? 'bg-discord-primary text-white'
Expand Down
31 changes: 16 additions & 15 deletions src/components/UserArea.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useCallback } from 'react'
import { useAuth } from '../hooks/useAuth'
import OnlineUsers from './OnlineUsers'
import { supabase } from '../integrations/supabase/client'
import { toast } from 'sonner'
import { Server } from '../integrations/supabase/types'

interface UserAreaProps {
server?: any
server?: Server
}

interface UserSettings {
Expand All @@ -30,13 +31,7 @@ export default function UserArea({ server }: UserAreaProps) {
})
const [loading, setLoading] = useState(false)

useEffect(() => {
if (user) {
loadUserSettings()
}
}, [user])

const loadUserSettings = async () => {
const loadUserSettings = useCallback(async () => {
if (!user) return
try {
const { data, error } = await supabase
Expand Down Expand Up @@ -73,7 +68,13 @@ export default function UserArea({ server }: UserAreaProps) {
} catch (error) {
console.error('Error loading user settings:', error)
}
}
}, [user])

useEffect(() => {
if (user) {
loadUserSettings()
}
}, [user, loadUserSettings])

const updateUserStatus = async (status: string) => {
if (!user) return
Expand All @@ -95,8 +96,8 @@ export default function UserArea({ server }: UserAreaProps) {
setUserSettings(prev => ({ ...prev, status }))
setShowStatusMenu(false)
toast.success('Status updated successfully!')
} catch (error: any) {
toast.error(`Failed to update status: ${error.message}`)
} catch (error) {
toast.error(`Failed to update status: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand All @@ -121,8 +122,8 @@ export default function UserArea({ server }: UserAreaProps) {

setShowSettings(false)
toast.success('Settings saved successfully!')
} catch (error: any) {
toast.error(`Failed to save settings: ${error.message}`)
} catch (error) {
toast.error(`Failed to save settings: ${error instanceof Error ? error.message : 'Unknown error'}`)
} finally {
setLoading(false)
}
Expand Down Expand Up @@ -154,7 +155,7 @@ export default function UserArea({ server }: UserAreaProps) {
<div className="flex flex-col h-full">
{/* Online Users */}
<div className="flex-1 overflow-y-auto">
<OnlineUsers server={server} />
<OnlineUsers server={server || null} />
</div>

{/* User Info Bar */}
Expand Down
Loading