hensei-web/app/api/auth/signup/route.ts
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

import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { postToApi } from '~/app/lib/api-utils'
// Signup request schema
const SignupSchema = z.object({
username: z.string()
.min(3, 'Username must be at least 3 characters')
.max(20, 'Username must be less than 20 characters')
.regex(/^[a-zA-Z0-9_-]+$/, 'Username can only contain letters, numbers, underscores, and hyphens'),
email: z.string().email('Invalid email format'),
password: z.string().min(8, 'Password must be at least 8 characters'),
password_confirmation: z.string()
}).refine(data => data.password === data.password_confirmation, {
message: "Passwords don't match",
path: ['password_confirmation']
})
export async function POST(request: NextRequest) {
try {
// Parse and validate request body
const body = await request.json()
const validatedData = SignupSchema.parse(body)
// Call signup endpoint
const response = await postToApi('/users', {
user: {
username: validatedData.username,
email: validatedData.email,
password: validatedData.password,
password_confirmation: validatedData.password_confirmation
}
})
// Return created user info
return NextResponse.json({
success: true,
user: {
username: response.username,
email: response.email
}
}, { status: 201 })
} catch (error) {
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Validation error', details: error.errors },
{ status: 400 }
)
}
// Handle specific API errors
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
)
}
}
}
console.error('Signup error:', error)
return NextResponse.json(
{ error: 'Signup failed' },
{ status: 500 }
)
}
}