Skip to content

Commit c3acf29

Browse files
committed
fix: resolve React Hooks violations in Language, ThemeToggle, and DonationPopup
1 parent 7178e98 commit c3acf29

File tree

4 files changed

+40
-47
lines changed

4 files changed

+40
-47
lines changed

dashboard/src/components/DonationPopup.tsx

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Heart, X } from 'lucide-react'
2-
import { useEffect, useState } from 'react'
2+
import { useCallback, useEffect, useState } from 'react'
33
import { useTranslation } from 'react-i18next'
44
import { Button } from './ui/button'
55
import { cn } from '@/lib/utils'
@@ -108,12 +108,32 @@ export default function DonationPopup() {
108108
const [isVisible, setIsVisible] = useState(false)
109109
const [isAnimating, setIsAnimating] = useState(false)
110110

111-
// Don't show popup if user is not authenticated
112-
if (!getAuthToken()) {
113-
return null
114-
}
111+
const showPopup = useCallback(() => {
112+
const now = Date.now()
113+
// Update storage: set lastShown to now and nextShowTime to 3 days from now
114+
const nextShowTime = new Date(now + DAYS_BETWEEN_SHOWS * 24 * 60 * 60 * 1000).toISOString()
115+
setStorageData({
116+
lastShown: new Date(now).toISOString(),
117+
nextShowTime,
118+
})
119+
120+
// Make visible immediately
121+
setIsVisible(true)
122+
123+
// Start animation after a frame for smooth CSS transition
124+
requestAnimationFrame(() => {
125+
requestAnimationFrame(() => {
126+
setIsAnimating(true)
127+
})
128+
})
129+
}, [])
115130

116131
useEffect(() => {
132+
// Don't show popup if user is not authenticated
133+
if (!getAuthToken()) {
134+
return
135+
}
136+
117137
const checkShouldShow = () => {
118138
const data = getStorageData()
119139
const now = Date.now()
@@ -140,26 +160,11 @@ export default function DonationPopup() {
140160
}
141161

142162
checkShouldShow()
143-
}, [])
163+
}, [showPopup])
144164

145-
const showPopup = () => {
146-
const now = Date.now()
147-
// Update storage: set lastShown to now and nextShowTime to 3 days from now
148-
const nextShowTime = new Date(now + DAYS_BETWEEN_SHOWS * 24 * 60 * 60 * 1000).toISOString()
149-
setStorageData({
150-
lastShown: new Date(now).toISOString(),
151-
nextShowTime,
152-
})
153-
154-
// Make visible immediately
155-
setIsVisible(true)
156-
157-
// Start animation after a frame for smooth CSS transition
158-
requestAnimationFrame(() => {
159-
requestAnimationFrame(() => {
160-
setIsAnimating(true)
161-
})
162-
})
165+
// Don't render popup if user is not authenticated
166+
if (!getAuthToken()) {
167+
return null
163168
}
164169

165170
const handleClose = () => {

dashboard/src/components/Language.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
import { Button } from '@/components/ui/button'
22
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
33
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
4-
import { useSidebar } from '@/components/ui/sidebar'
4+
import { SidebarContext } from '@/components/ui/sidebar'
55
import { LanguagesIcon } from 'lucide-react'
6+
import { useContext } from 'react'
67
import { useTranslation } from 'react-i18next'
78

89
export const Language: React.FC = () => {
910
const { i18n, t } = useTranslation()
1011

1112
// Safely get sidebar state, defaulting to 'expanded' if not available
12-
let sidebarState: 'expanded' | 'collapsed' = 'expanded'
13-
let isMobile = false
14-
try {
15-
const { state, isMobile: mobileFlag } = useSidebar()
16-
sidebarState = state
17-
isMobile = mobileFlag
18-
} catch (error) {
19-
// useSidebar is not available, use default state
20-
console.warn('useSidebar not available in Language component, using default expanded state')
21-
}
13+
const sidebarContext = useContext(SidebarContext)
14+
const sidebarState: 'expanded' | 'collapsed' = sidebarContext?.state ?? 'expanded'
15+
const isMobile = sidebarContext?.isMobile ?? false
2216

2317
const changeLanguage = async (lang: string) => {
2418
await i18n.changeLanguage(lang)

dashboard/src/components/theme-toggle.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,19 @@ import { Theme, useTheme } from '@/components/theme-provider'
22
import { Button } from '@/components/ui/button'
33
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
44
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
5-
import { useSidebar } from '@/components/ui/sidebar'
5+
import { SidebarContext } from '@/components/ui/sidebar'
66
import { Monitor, Moon, Sun } from 'lucide-react'
7-
import { useCallback } from 'react'
7+
import { useCallback, useContext } from 'react'
88
import { useTranslation } from 'react-i18next'
99

1010
export function ThemeToggle() {
1111
const { setTheme } = useTheme()
1212
const { t } = useTranslation()
1313

1414
// Safely get sidebar state, defaulting to 'expanded' if not available
15-
let sidebarState: 'expanded' | 'collapsed' = 'expanded'
16-
let isMobile = false
17-
try {
18-
const { state, isMobile: mobileFlag } = useSidebar()
19-
sidebarState = state
20-
isMobile = mobileFlag
21-
} catch (error) {
22-
// useSidebar is not available, use default state
23-
console.warn('useSidebar not available, using default expanded state')
24-
}
15+
const sidebarContext = useContext(SidebarContext)
16+
const sidebarState: 'expanded' | 'collapsed' = sidebarContext?.state ?? 'expanded'
17+
const isMobile = sidebarContext?.isMobile ?? false
2518

2619
const toggleTheme = useCallback(
2720
(theme: Theme) => {

dashboard/src/components/ui/sidebar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,4 +611,5 @@ export {
611611
SidebarSeparator,
612612
SidebarTrigger,
613613
useSidebar,
614+
SidebarContext,
614615
}

0 commit comments

Comments
 (0)