hensei-web/app/components/UpdateToastClient.tsx
Justin Edmund e4b7f0c356
Fix TypeScript errors for production build (#436)
## Summary
Fixed multiple TypeScript errors that were preventing the production
build from completing on Railway.

## Changes Made

### Nullable Type Fixes
- Fixed `searchParams.toString()` calls with optional chaining (`?.`)
and fallback values
- Fixed `pathname` nullable access in UpdateToastClient
- Added fallbacks for undefined values in translation interpolations

### Type Consistency Fixes
- Fixed recency parameter handling (string from URL, converted to number
internally)
- Removed duplicate local interface definitions for Party and User types
- Fixed Party type mismatches by using global type definitions

### API Route Error Handling
- Fixed error type checking in catch blocks for login/signup routes
- Added proper type guards for axios error objects

### Component Props Fixes
- Fixed RadixSelect.Trigger by removing invalid placeholder prop
- Fixed Toast and Tooltip components by using Omit to exclude
conflicting content type
- Added missing onAdvancedFilter prop to FilterBar components
- Fixed PartyFooter props with required parameters

## Test Plan
- [x] Fixed all TypeScript compilation errors locally
- [ ] Production build should complete successfully on Railway
- [ ] All affected components should function correctly

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-04 01:47:10 -07:00

73 lines
No EOL
2.2 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { usePathname } from 'next/navigation'
import { add, format } from 'date-fns'
import { getCookie } from 'cookies-next'
import { useSnapshot } from 'valtio'
import { appState } from '~/utils/appState'
import UpdateToast from '~/components/toasts/UpdateToast'
interface UpdateToastClientProps {
initialVersion?: AppUpdate | null
}
export default function UpdateToastClient({ initialVersion }: UpdateToastClientProps) {
const pathname = usePathname()
const [updateToastOpen, setUpdateToastOpen] = useState(false)
const { version } = useSnapshot(appState)
// Use initialVersion for SSR, then switch to appState version after hydration
const effectiveVersion = version?.updated_at ? version : initialVersion
useEffect(() => {
if (effectiveVersion && effectiveVersion.updated_at) {
const cookie = getToastCookie()
const now = new Date()
const updatedAt = new Date(effectiveVersion.updated_at)
const validUntil = add(updatedAt, { days: 7 })
if (now < validUntil && !cookie.seen) setUpdateToastOpen(true)
}
}, [effectiveVersion?.updated_at])
function getToastCookie() {
if (appState.version && appState.version.updated_at !== '') {
const updatedAt = new Date(appState.version.updated_at)
const cookieValues = getCookie(
`update-${format(updatedAt, 'yyyy-MM-dd')}`
)
return cookieValues
? (JSON.parse(cookieValues as string) as { seen: true })
: { seen: false }
} else {
return { seen: false }
}
}
function handleToastActionClicked() {
setUpdateToastOpen(false)
}
function handleToastClosed() {
setUpdateToastOpen(false)
}
const path = pathname?.replaceAll('/', '') || ''
// Only render toast if we have valid version data with update_type
if (!['about', 'updates', 'roadmap'].includes(path) && effectiveVersion && effectiveVersion.update_type) {
return (
<UpdateToast
open={updateToastOpen}
updateType={effectiveVersion.update_type}
onActionClicked={handleToastActionClicked}
onCloseClicked={handleToastClosed}
lastUpdated={effectiveVersion.updated_at}
/>
)
}
return null
}