mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 12:51:13 -05:00
346 lines
9.0 KiB
TypeScript
346 lines
9.0 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import { ComboboxOption } from '@/components/ui/combobox';
|
|
import { toast } from 'sonner';
|
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
|
|
|
export function useCountries() {
|
|
const [countries, setCountries] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchCountries() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('locations')
|
|
.select('country')
|
|
.not('country', 'is', null);
|
|
|
|
if (error) throw error;
|
|
|
|
const uniqueCountries = Array.from(
|
|
new Set(data?.map(item => item.country) || [])
|
|
).sort();
|
|
|
|
setCountries(
|
|
uniqueCountries.map(country => ({
|
|
label: country,
|
|
value: country.toLowerCase().replace(/\s+/g, '_')
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch countries' });
|
|
toast.error('Failed to load countries', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setCountries([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchCountries();
|
|
}, []);
|
|
|
|
return { countries, loading };
|
|
}
|
|
|
|
export function useStatesProvinces(country?: string) {
|
|
const [statesProvinces, setStatesProvinces] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!country) {
|
|
setStatesProvinces([]);
|
|
return;
|
|
}
|
|
|
|
async function fetchStatesProvinces() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('locations')
|
|
.select('state_province')
|
|
.eq('country', country || '')
|
|
.not('state_province', 'is', null);
|
|
|
|
if (error) throw error;
|
|
|
|
const uniqueStates = Array.from(
|
|
new Set(data?.map(item => item.state_province).filter((s): s is string => s != null) || [])
|
|
).sort();
|
|
|
|
setStatesProvinces(
|
|
uniqueStates.map(state => ({
|
|
label: state,
|
|
value: state.toLowerCase().replace(/\s+/g, '_')
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, {
|
|
action: 'Fetch states/provinces',
|
|
metadata: { country },
|
|
});
|
|
toast.error('Failed to load states/provinces', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setStatesProvinces([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchStatesProvinces();
|
|
}, [country]);
|
|
|
|
return { statesProvinces, loading };
|
|
}
|
|
|
|
export function useManufacturers() {
|
|
const [manufacturers, setManufacturers] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchManufacturers() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('companies')
|
|
.select('id, name')
|
|
.eq('company_type', 'manufacturer')
|
|
.order('name');
|
|
|
|
if (error) throw error;
|
|
|
|
setManufacturers(
|
|
(data || []).map(company => ({
|
|
label: company.name,
|
|
value: company.id
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch manufacturers' });
|
|
toast.error('Failed to load manufacturers', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setManufacturers([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchManufacturers();
|
|
}, []);
|
|
|
|
return { manufacturers, loading };
|
|
}
|
|
|
|
export function useRideModels(manufacturerId?: string) {
|
|
const [rideModels, setRideModels] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!manufacturerId) {
|
|
setRideModels([]);
|
|
return;
|
|
}
|
|
|
|
async function fetchRideModels() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('ride_models')
|
|
.select('id, name')
|
|
.eq('manufacturer_id', manufacturerId || '')
|
|
.order('name');
|
|
|
|
if (error) throw error;
|
|
|
|
setRideModels(
|
|
(data || []).map(model => ({
|
|
label: model.name,
|
|
value: model.id
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, {
|
|
action: 'Fetch ride models',
|
|
metadata: { manufacturerId },
|
|
});
|
|
toast.error('Failed to load ride models', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setRideModels([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchRideModels();
|
|
}, [manufacturerId]);
|
|
|
|
return { rideModels, loading };
|
|
}
|
|
|
|
export function useCompanyHeadquarters() {
|
|
const [headquarters, setHeadquarters] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchHeadquarters() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('companies')
|
|
.select('headquarters_location')
|
|
.not('headquarters_location', 'is', null);
|
|
|
|
if (error) throw error;
|
|
|
|
const uniqueHeadquarters = Array.from(
|
|
new Set(data?.map(item => item.headquarters_location).filter((hq): hq is string => hq != null) || [])
|
|
).sort();
|
|
|
|
setHeadquarters(
|
|
uniqueHeadquarters.map(hq => ({
|
|
label: hq,
|
|
value: hq.toLowerCase().replace(/\s+/g, '_')
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch headquarters' });
|
|
toast.error('Failed to load headquarters', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setHeadquarters([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchHeadquarters();
|
|
}, []);
|
|
|
|
return { headquarters, loading };
|
|
}
|
|
|
|
export function useOperators() {
|
|
const [operators, setOperators] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchOperators() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('companies')
|
|
.select('id, name')
|
|
.eq('company_type', 'operator')
|
|
.order('name');
|
|
|
|
if (error) throw error;
|
|
|
|
setOperators(
|
|
(data || []).map(company => ({
|
|
label: company.name,
|
|
value: company.id
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch operators' });
|
|
toast.error('Failed to load operators', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setOperators([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchOperators();
|
|
}, []);
|
|
|
|
return { operators, loading };
|
|
}
|
|
|
|
export function usePropertyOwners() {
|
|
const [propertyOwners, setPropertyOwners] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchPropertyOwners() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('companies')
|
|
.select('id, name')
|
|
.eq('company_type', 'property_owner')
|
|
.order('name');
|
|
|
|
if (error) throw error;
|
|
|
|
setPropertyOwners(
|
|
(data || []).map(company => ({
|
|
label: company.name,
|
|
value: company.id
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch property owners' });
|
|
toast.error('Failed to load property owners', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setPropertyOwners([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchPropertyOwners();
|
|
}, []);
|
|
|
|
return { propertyOwners, loading };
|
|
}
|
|
|
|
/**
|
|
* Hook to fetch all parks for autocomplete
|
|
* Returns parks as combobox options
|
|
*/
|
|
export function useParks() {
|
|
const [parks, setParks] = useState<ComboboxOption[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
async function fetchParks() {
|
|
setLoading(true);
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('parks')
|
|
.select('id, name, slug')
|
|
.order('name');
|
|
|
|
if (error) throw error;
|
|
|
|
setParks(
|
|
(data || []).map(park => ({
|
|
label: park.name,
|
|
value: park.id
|
|
}))
|
|
);
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, { action: 'Fetch parks' });
|
|
toast.error('Failed to load parks', {
|
|
description: 'Please refresh the page and try again.',
|
|
});
|
|
setParks([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchParks();
|
|
}, []);
|
|
|
|
return { parks, loading };
|
|
} |