Fix TypeScript errors for production build
- Fixed nullable searchParams with optional chaining and fallbacks - Fixed recency type handling (string from URL, number internally) - Removed duplicate Party/User interface definitions, use global types - Fixed error handling in API routes with proper type checking - Fixed props access in UI components (placeholder, content types) - Added missing required props to components - Fixed type mismatches with next-intl rich text interpolation
This commit is contained in:
parent
02676fd7d4
commit
d880643fca
15 changed files with 56 additions and 76 deletions
|
|
@ -24,25 +24,6 @@ interface Pagination {
|
|||
record_count: number;
|
||||
}
|
||||
|
||||
interface Party {
|
||||
id: string;
|
||||
shortcode: string;
|
||||
name: string;
|
||||
element: number;
|
||||
// Add other properties as needed
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
avatar: {
|
||||
picture: string;
|
||||
element: string;
|
||||
};
|
||||
gender: string;
|
||||
// Add other properties as needed
|
||||
}
|
||||
|
||||
interface Props {
|
||||
initialData: {
|
||||
user: User;
|
||||
|
|
@ -74,7 +55,7 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
const [fetching, setFetching] = useState(false)
|
||||
const [element, setElement] = useState(initialElement || 0)
|
||||
const [raid, setRaid] = useState(initialRaid || '')
|
||||
const [recency, setRecency] = useState(initialRecency || '')
|
||||
const [recency, setRecency] = useState(initialRecency ? parseInt(initialRecency, 10) : 0)
|
||||
|
||||
// Initialize app state with raid groups
|
||||
useEffect(() => {
|
||||
|
|
@ -85,7 +66,7 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
|
||||
// Update URL when filters change
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
const params = new URLSearchParams(searchParams?.toString() ?? '')
|
||||
|
||||
// Update or remove parameters based on filter values
|
||||
if (element) {
|
||||
|
|
@ -101,14 +82,14 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
}
|
||||
|
||||
if (recency) {
|
||||
params.set('recency', recency)
|
||||
params.set('recency', recency.toString())
|
||||
} else {
|
||||
params.delete('recency')
|
||||
}
|
||||
|
||||
// Only update URL if filters are changed
|
||||
const newQueryString = params.toString()
|
||||
const currentQuery = searchParams.toString()
|
||||
const currentQuery = searchParams?.toString() ?? ''
|
||||
|
||||
if (newQueryString !== currentQuery) {
|
||||
router.push(`/${initialData.user.username}${newQueryString ? `?${newQueryString}` : ''}`)
|
||||
|
|
@ -128,7 +109,7 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
|
||||
if (element) url.searchParams.set('element', element.toString())
|
||||
if (raid) url.searchParams.set('raid_id', raid)
|
||||
if (recency) url.searchParams.set('recency', recency)
|
||||
if (recency) url.searchParams.set('recency', recency.toString())
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
headers: {
|
||||
|
|
@ -163,7 +144,7 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
setElement(filters.element || 0)
|
||||
}
|
||||
if ('recency' in filters) {
|
||||
setRecency(filters.recency || '')
|
||||
setRecency(filters.recency || 0)
|
||||
}
|
||||
if ('raid' in filters) {
|
||||
setRaid(filters.raid || '')
|
||||
|
|
@ -226,6 +207,7 @@ const ProfilePageClient: React.FC<Props> = ({
|
|||
<FilterBar
|
||||
defaultFilterset={defaultFilterset}
|
||||
onFilter={receiveFilters}
|
||||
onAdvancedFilter={receiveFilters}
|
||||
persistFilters={false}
|
||||
element={element}
|
||||
raid={raid}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,14 @@ const PartyPageClient: React.FC<Props> = ({ party, raidGroups }) => {
|
|||
handleTabChanged={handleTabChanged}
|
||||
pushHistory={pushHistory}
|
||||
/>
|
||||
<PartyFooter party={party} />
|
||||
<PartyFooter
|
||||
party={party}
|
||||
new={false}
|
||||
editable={false}
|
||||
raidGroups={raidGroups}
|
||||
remixCallback={() => {}}
|
||||
updateCallback={async () => ({})}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,6 @@ import { defaultFilterset } from '~/utils/defaultFilters'
|
|||
import { appState } from '~/utils/appState'
|
||||
|
||||
// Types
|
||||
interface Party {
|
||||
id: string;
|
||||
shortcode: string;
|
||||
name: string;
|
||||
element: number;
|
||||
// Add other properties as needed
|
||||
}
|
||||
|
||||
interface Props {
|
||||
initialData: {
|
||||
|
|
@ -52,7 +45,7 @@ const SavedPageClient: React.FC<Props> = ({
|
|||
const [parties, setParties] = useState<Party[]>(initialData.teams)
|
||||
const [element, setElement] = useState(initialElement || 0)
|
||||
const [raid, setRaid] = useState(initialRaid || '')
|
||||
const [recency, setRecency] = useState(initialRecency || '')
|
||||
const [recency, setRecency] = useState(initialRecency ? parseInt(initialRecency, 10) : 0)
|
||||
const [fetching, setFetching] = useState(false)
|
||||
|
||||
// Initialize app state with raid groups
|
||||
|
|
@ -64,7 +57,7 @@ const SavedPageClient: React.FC<Props> = ({
|
|||
|
||||
// Update URL when filters change
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
const params = new URLSearchParams(searchParams?.toString() ?? '')
|
||||
|
||||
// Update or remove parameters based on filter values
|
||||
if (element) {
|
||||
|
|
@ -80,14 +73,14 @@ const SavedPageClient: React.FC<Props> = ({
|
|||
}
|
||||
|
||||
if (recency) {
|
||||
params.set('recency', recency)
|
||||
params.set('recency', recency.toString())
|
||||
} else {
|
||||
params.delete('recency')
|
||||
}
|
||||
|
||||
// Only update URL if filters are changed
|
||||
const newQueryString = params.toString()
|
||||
const currentQuery = searchParams.toString()
|
||||
const currentQuery = searchParams?.toString() ?? ''
|
||||
|
||||
if (newQueryString !== currentQuery) {
|
||||
router.push(`/saved${newQueryString ? `?${newQueryString}` : ''}`)
|
||||
|
|
@ -100,7 +93,7 @@ const SavedPageClient: React.FC<Props> = ({
|
|||
setElement(filters.element || 0)
|
||||
}
|
||||
if ('recency' in filters) {
|
||||
setRecency(filters.recency || '')
|
||||
setRecency(filters.recency || 0)
|
||||
}
|
||||
if ('raid' in filters) {
|
||||
setRaid(filters.raid || '')
|
||||
|
|
@ -180,6 +173,7 @@ const SavedPageClient: React.FC<Props> = ({
|
|||
<FilterBar
|
||||
defaultFilterset={defaultFilterset}
|
||||
onFilter={receiveFilters}
|
||||
onAdvancedFilter={receiveFilters}
|
||||
persistFilters={false}
|
||||
element={element}
|
||||
raid={raid}
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ export default async function SavedPage({
|
|||
let filteredTeams = savedTeamsData.results || [];
|
||||
|
||||
if (element) {
|
||||
filteredTeams = filteredTeams.filter(party => party.element === element)
|
||||
filteredTeams = filteredTeams.filter((party: any) => party.element === element)
|
||||
}
|
||||
|
||||
if (raid) {
|
||||
filteredTeams = filteredTeams.filter(party => party.raid?.id === raid)
|
||||
filteredTeams = filteredTeams.filter((party: any) => party.raid?.id === raid)
|
||||
}
|
||||
|
||||
// Prepare data for client component
|
||||
|
|
|
|||
|
|
@ -23,14 +23,6 @@ import LoadingRep from '~/components/reps/LoadingRep'
|
|||
import ErrorSection from '~/components/ErrorSection'
|
||||
|
||||
// Types
|
||||
interface Party {
|
||||
id: string;
|
||||
shortcode: string;
|
||||
name: string;
|
||||
element: number;
|
||||
// Add other properties as needed
|
||||
}
|
||||
|
||||
interface Pagination {
|
||||
current_page: number;
|
||||
total_pages: number;
|
||||
|
|
@ -69,7 +61,7 @@ const TeamsPageClient: React.FC<Props> = ({
|
|||
const [fetching, setFetching] = useState(false)
|
||||
const [element, setElement] = useState(initialElement || 0)
|
||||
const [raid, setRaid] = useState(initialRaid || '')
|
||||
const [recency, setRecency] = useState(initialRecency || '')
|
||||
const [recency, setRecency] = useState(initialRecency ? parseInt(initialRecency, 10) : 0)
|
||||
const [advancedFilters, setAdvancedFilters] = useState({})
|
||||
|
||||
const { toggleFavorite } = useFavorites(parties, setParties)
|
||||
|
|
@ -83,7 +75,7 @@ const TeamsPageClient: React.FC<Props> = ({
|
|||
|
||||
// Update URL when filters change
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
const params = new URLSearchParams(searchParams?.toString() ?? '')
|
||||
|
||||
// Update or remove parameters based on filter values
|
||||
if (element) {
|
||||
|
|
@ -99,14 +91,14 @@ const TeamsPageClient: React.FC<Props> = ({
|
|||
}
|
||||
|
||||
if (recency) {
|
||||
params.set('recency', recency)
|
||||
params.set('recency', recency.toString())
|
||||
} else {
|
||||
params.delete('recency')
|
||||
}
|
||||
|
||||
// Only update URL if filters are changed
|
||||
const newQueryString = params.toString()
|
||||
const currentQuery = searchParams.toString()
|
||||
const currentQuery = searchParams?.toString() ?? ''
|
||||
|
||||
if (newQueryString !== currentQuery) {
|
||||
router.push(`/teams${newQueryString ? `?${newQueryString}` : ''}`)
|
||||
|
|
@ -126,7 +118,7 @@ const TeamsPageClient: React.FC<Props> = ({
|
|||
|
||||
if (element) url.searchParams.set('element', element.toString())
|
||||
if (raid) url.searchParams.set('raid', raid)
|
||||
if (recency) url.searchParams.set('recency', recency)
|
||||
if (recency) url.searchParams.set('recency', recency.toString())
|
||||
|
||||
const response = await fetch(url.toString())
|
||||
const data = await response.json()
|
||||
|
|
@ -150,7 +142,7 @@ const TeamsPageClient: React.FC<Props> = ({
|
|||
setElement(filters.element || 0)
|
||||
}
|
||||
if ('recency' in filters) {
|
||||
setRecency(filters.recency || '')
|
||||
setRecency(filters.recency || 0)
|
||||
}
|
||||
if ('raid' in filters) {
|
||||
setRaid(filters.raid || '')
|
||||
|
|
|
|||
|
|
@ -84,11 +84,14 @@ export async function POST(request: NextRequest) {
|
|||
}
|
||||
|
||||
// For authentication errors
|
||||
if (error.response?.status === 401) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid email or password' },
|
||||
{ status: 401 }
|
||||
)
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
const axiosError = error as any
|
||||
if (axiosError.response?.status === 401) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid email or password' },
|
||||
{ status: 401 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
console.error('Login error:', error)
|
||||
|
|
|
|||
|
|
@ -49,15 +49,18 @@ export async function POST(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Handle specific API errors
|
||||
if (error.response?.data?.error) {
|
||||
const apiError = error.response.data.error
|
||||
|
||||
// Username or email already in use
|
||||
if (apiError.includes('username') || apiError.includes('email')) {
|
||||
return NextResponse.json(
|
||||
{ error: apiError },
|
||||
{ status: 409 } // Conflict
|
||||
)
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
const axiosError = error as any
|
||||
if (axiosError.response?.data?.error) {
|
||||
const apiError = axiosError.response.data.error
|
||||
|
||||
// Username or email already in use
|
||||
if (apiError.includes('username') || apiError.includes('email')) {
|
||||
return NextResponse.json(
|
||||
{ error: apiError },
|
||||
{ status: 409 } // Conflict
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export default function UpdateToastClient({ initialVersion }: UpdateToastClientP
|
|||
setUpdateToastOpen(false)
|
||||
}
|
||||
|
||||
const path = pathname.replaceAll('/', '')
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ const CharacterUnit = ({
|
|||
message={
|
||||
<>
|
||||
{t.rich('modals.characters.messages.remove', {
|
||||
character: gridCharacter?.object.name[locale],
|
||||
character: gridCharacter?.object.name[locale] || '',
|
||||
strong: (chunks) => <strong>{chunks}</strong>
|
||||
})}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ const Editor = ({
|
|||
renderLabel({ options, node }) {
|
||||
return `${node.attrs.id.name[locale] ?? node.attrs.id.granblue_en}`
|
||||
},
|
||||
suggestion: mentionSuggestionOptions,
|
||||
suggestion: mentionSuggestionOptions as any,
|
||||
HTMLAttributes: {
|
||||
class: classNames({
|
||||
[styles.mention]: true,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ const Popover = React.forwardRef<HTMLDivElement, Props>(function Popover(
|
|||
[styles.empty]: true,
|
||||
})}
|
||||
>
|
||||
{props.placeholder}
|
||||
{props.trigger?.placeholder}
|
||||
</span>
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ const Select = React.forwardRef<HTMLButtonElement, Props>(function Select(
|
|||
<RadixSelect.Trigger
|
||||
autoFocus={props.autoFocus || false}
|
||||
className={triggerClasses}
|
||||
placeholder={props.placeholder}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
{props.icon?.src && <img alt={props.icon.alt} src={props.icon.src} />}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import classNames from 'classnames'
|
|||
import * as ToastPrimitive from '@radix-ui/react-toast'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
interface Props extends ToastPrimitive.ToastProps {
|
||||
interface Props extends Omit<ToastPrimitive.ToastProps, 'content'> {
|
||||
altText: string
|
||||
className?: string
|
||||
title?: string
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { PropsWithChildren } from 'react'
|
|||
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
interface Props extends TooltipPrimitive.TooltipContentProps {
|
||||
interface Props extends Omit<TooltipPrimitive.TooltipContentProps, 'content'> {
|
||||
content: React.ReactNode
|
||||
open?: boolean
|
||||
onOpenChange?: (open: boolean) => void
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ const GuidebookUnit = ({
|
|||
message={
|
||||
<>
|
||||
{t.rich('modals.guidebooks.messages.remove', {
|
||||
guidebook: guidebook?.name[locale],
|
||||
guidebook: guidebook?.name[locale] || '',
|
||||
strong: (chunks) => <strong>{chunks}</strong>
|
||||
})}
|
||||
</>
|
||||
|
|
|
|||
Loading…
Reference in a new issue