feat: add city/state/country to complex, new settings page with sidebar, and Biome linting

- Added city, state, and country optional fields to Complex model
- Updated onboarding to include optional location fields
- Created new settings page with sidebar navigation (Datos del Complejo, Canchas)
- Replaced ESLint with Biome for frontend and backend linting
- Added parallel dev script with concurrently
- Migrated register-routes to use direct app.route() pattern
This commit is contained in:
Jose Selesan
2026-04-10 15:36:15 -03:00
parent 77004b14b0
commit 9ee98a4cb4
129 changed files with 2929 additions and 3186 deletions

View File

@@ -1,35 +1,35 @@
import { useEffect, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { type Court, type CreateCourtInput } from '@repo/api-contract'
import { apiClient } from '@/lib/api-client'
import { setCurrentComplexSlug } from '@/lib/current-complex'
import { CourtFormSection } from './components/court-form-section'
import { CourtListSection } from './components/court-list-section'
import { apiClient } from '@/lib/api-client';
import { setCurrentComplexSlug } from '@/lib/current-complex';
import { type Court, type CreateCourtInput } from '@repo/api-contract';
import { useQuery } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { CourtFormSection } from './components/court-form-section';
import { CourtListSection } from './components/court-list-section';
type ComplexCourtsPageProps = {
complexSlug: string
}
complexSlug: string;
};
export function ComplexCourtsPage({ complexSlug }: ComplexCourtsPageProps) {
const [editingCourt, setEditingCourt] = useState<Court | null>(null)
const [initialDraft, setInitialDraft] = useState<CreateCourtInput | null>(null)
const [editingCourt, setEditingCourt] = useState<Court | null>(null);
const [initialDraft, setInitialDraft] = useState<CreateCourtInput | null>(null);
useEffect(() => {
setCurrentComplexSlug(complexSlug)
}, [complexSlug])
setCurrentComplexSlug(complexSlug);
}, [complexSlug]);
const complexQuery = useQuery({
queryKey: ['complex-by-slug', complexSlug],
queryFn: () => apiClient.complexes.getBySlug(complexSlug),
})
});
const complexId = complexQuery.data?.id ?? null
const complexId = complexQuery.data?.id ?? null;
const courtsQuery = useQuery({
queryKey: ['courts', complexId],
enabled: Boolean(complexId),
queryFn: () => apiClient.courts.listByComplex(complexId as string),
})
});
return (
<main className="mx-auto w-full max-w-6xl space-y-6 px-4 py-4 sm:px-6">
@@ -47,7 +47,7 @@ export function ComplexCourtsPage({ complexSlug }: ComplexCourtsPageProps) {
editingCourt={editingCourt}
initialDraft={initialDraft}
onCancelEdit={() => {
setEditingCourt(null)
setEditingCourt(null);
}}
/>
@@ -56,7 +56,7 @@ export function ComplexCourtsPage({ complexSlug }: ComplexCourtsPageProps) {
isLoading={courtsQuery.isLoading}
isError={courtsQuery.isError}
onDuplicateCourt={(court) => {
setEditingCourt(null)
setEditingCourt(null);
setInitialDraft({
name: `${court.name} - Copy`,
sportId: court.sportId,
@@ -67,15 +67,15 @@ export function ComplexCourtsPage({ complexSlug }: ComplexCourtsPageProps) {
startTime: slot.startTime,
endTime: slot.endTime,
})),
})
window.scrollTo({ top: 0, behavior: 'smooth' })
});
window.scrollTo({ top: 0, behavior: 'smooth' });
}}
onEditCourt={(court) => {
setInitialDraft(null)
setEditingCourt(court)
window.scrollTo({ top: 0, behavior: 'smooth' })
setInitialDraft(null);
setEditingCourt(court);
window.scrollTo({ top: 0, behavior: 'smooth' });
}}
/>
</main>
)
);
}