mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-29 05:47:06 -05:00
Compare commits
3 Commits
e14c11d994
...
2ce837f376
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ce837f376 | ||
|
|
8281fb9852 | ||
|
|
8ce7775324 |
@@ -163,7 +163,11 @@ export function ManufacturerForm({ onSubmit, onCancel, initialData }: Manufactur
|
|||||||
{/* Additional Details */}
|
{/* Additional Details */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<FlexibleDateInput
|
<FlexibleDateInput
|
||||||
value={watch('founded_date') ? parseDateOnly(watch('founded_date')) : undefined}
|
value={(() => {
|
||||||
|
const dateValue = watch('founded_date');
|
||||||
|
if (!dateValue) return undefined;
|
||||||
|
return parseDateOnly(dateValue);
|
||||||
|
})()}
|
||||||
precision={(watch('founded_date_precision') as DatePrecision) || 'year'}
|
precision={(watch('founded_date_precision') as DatePrecision) || 'year'}
|
||||||
onChange={(date, precision) => {
|
onChange={(date, precision) => {
|
||||||
setValue('founded_date', date ? toDateOnly(date) : undefined);
|
setValue('founded_date', date ? toDateOnly(date) : undefined);
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import { supabase } from '@/integrations/supabase/client';
|
|||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
interface DuplicateStats {
|
interface DuplicateStats {
|
||||||
date: string;
|
date: string | null;
|
||||||
total_attempts: number;
|
total_attempts: number | null;
|
||||||
duplicates_prevented: number;
|
duplicates_prevented: number | null;
|
||||||
prevention_rate: number;
|
prevention_rate: number | null;
|
||||||
health_status: 'healthy' | 'warning' | 'critical';
|
health_status: 'healthy' | 'warning' | 'critical';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,11 +20,11 @@ interface RecentDuplicate {
|
|||||||
id: string;
|
id: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
channel: string;
|
channel: string;
|
||||||
idempotency_key: string;
|
idempotency_key: string | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
profiles?: {
|
profiles?: {
|
||||||
username: string;
|
username: string;
|
||||||
display_name: string;
|
display_name: string | null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +165,11 @@ export function NotificationDebugPanel() {
|
|||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{stats.map((stat) => (
|
{stats.map((stat) => (
|
||||||
<TableRow key={stat.date}>
|
<TableRow key={stat.date || 'unknown'}>
|
||||||
<TableCell>{format(new Date(stat.date), 'MMM d, yyyy')}</TableCell>
|
<TableCell>{stat.date ? format(new Date(stat.date), 'MMM d, yyyy') : 'N/A'}</TableCell>
|
||||||
<TableCell className="text-right">{stat.total_attempts}</TableCell>
|
<TableCell className="text-right">{stat.total_attempts ?? 0}</TableCell>
|
||||||
<TableCell className="text-right">{stat.duplicates_prevented}</TableCell>
|
<TableCell className="text-right">{stat.duplicates_prevented ?? 0}</TableCell>
|
||||||
<TableCell className="text-right">{stat.prevention_rate.toFixed(1)}%</TableCell>
|
<TableCell className="text-right">{stat.prevention_rate !== null ? stat.prevention_rate.toFixed(1) : 'N/A'}%</TableCell>
|
||||||
<TableCell>{getHealthBadge(stat.health_status)}</TableCell>
|
<TableCell>{getHealthBadge(stat.health_status)}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
{/* Dates */}
|
{/* Dates */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<FlexibleDateInput
|
<FlexibleDateInput
|
||||||
value={watch('opening_date') ? parseDateOnly(watch('opening_date')) : undefined}
|
value={watch('opening_date') ? parseDateOnly(watch('opening_date')!) : undefined}
|
||||||
precision={(watch('opening_date_precision') as DatePrecision) || 'day'}
|
precision={(watch('opening_date_precision') as DatePrecision) || 'day'}
|
||||||
onChange={(date, precision) => {
|
onChange={(date, precision) => {
|
||||||
setValue('opening_date', date ? toDateOnly(date) : undefined);
|
setValue('opening_date', date ? toDateOnly(date) : undefined);
|
||||||
@@ -388,7 +388,7 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FlexibleDateInput
|
<FlexibleDateInput
|
||||||
value={watch('closing_date') ? parseDateOnly(watch('closing_date')) : undefined}
|
value={watch('closing_date') ? parseDateOnly(watch('closing_date')!) : undefined}
|
||||||
precision={(watch('closing_date_precision') as DatePrecision) || 'day'}
|
precision={(watch('closing_date_precision') as DatePrecision) || 'day'}
|
||||||
onChange={(date, precision) => {
|
onChange={(date, precision) => {
|
||||||
setValue('closing_date', date ? toDateOnly(date) : undefined);
|
setValue('closing_date', date ? toDateOnly(date) : undefined);
|
||||||
@@ -632,7 +632,7 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
{/* Images */}
|
{/* Images */}
|
||||||
<EntityMultiImageUploader
|
<EntityMultiImageUploader
|
||||||
mode={isEditing ? 'edit' : 'create'}
|
mode={isEditing ? 'edit' : 'create'}
|
||||||
value={watch('images')}
|
value={watch('images') as ImageAssignments}
|
||||||
onChange={(images: ImageAssignments) => setValue('images', images)}
|
onChange={(images: ImageAssignments) => setValue('images', images)}
|
||||||
entityType="park"
|
entityType="park"
|
||||||
entityId={isEditing ? initialData?.id : undefined}
|
entityId={isEditing ? initialData?.id : undefined}
|
||||||
@@ -663,7 +663,7 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
<Dialog open={isOperatorModalOpen} onOpenChange={setIsOperatorModalOpen}>
|
<Dialog open={isOperatorModalOpen} onOpenChange={setIsOperatorModalOpen}>
|
||||||
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
||||||
<OperatorForm
|
<OperatorForm
|
||||||
initialData={tempNewOperator}
|
initialData={tempNewOperator || undefined}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
setTempNewOperator(data);
|
setTempNewOperator(data);
|
||||||
setIsOperatorModalOpen(false);
|
setIsOperatorModalOpen(false);
|
||||||
@@ -678,7 +678,7 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
<Dialog open={isPropertyOwnerModalOpen} onOpenChange={setIsPropertyOwnerModalOpen}>
|
<Dialog open={isPropertyOwnerModalOpen} onOpenChange={setIsPropertyOwnerModalOpen}>
|
||||||
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
||||||
<PropertyOwnerForm
|
<PropertyOwnerForm
|
||||||
initialData={tempNewPropertyOwner}
|
initialData={tempNewPropertyOwner || undefined}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
setTempNewPropertyOwner(data);
|
setTempNewPropertyOwner(data);
|
||||||
setIsPropertyOwnerModalOpen(false);
|
setIsPropertyOwnerModalOpen(false);
|
||||||
|
|||||||
@@ -326,10 +326,10 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
_technical_specifications: technicalSpecs,
|
_technical_specifications: technicalSpecs,
|
||||||
_coaster_statistics: coasterStats,
|
_coaster_statistics: coasterStats,
|
||||||
_name_history: formerNames,
|
_name_history: formerNames,
|
||||||
_tempNewPark: tempNewPark,
|
_tempNewPark: tempNewPark || undefined,
|
||||||
_tempNewManufacturer: tempNewManufacturer,
|
_tempNewManufacturer: tempNewManufacturer || undefined,
|
||||||
_tempNewDesigner: tempNewDesigner,
|
_tempNewDesigner: tempNewDesigner || undefined,
|
||||||
_tempNewRideModel: tempNewRideModel
|
_tempNewRideModel: tempNewRideModel || undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pass clean data to parent with extended fields
|
// Pass clean data to parent with extended fields
|
||||||
@@ -492,7 +492,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
// Show combobox for existing manufacturers
|
// Show combobox for existing manufacturers
|
||||||
<Combobox
|
<Combobox
|
||||||
options={manufacturers}
|
options={manufacturers}
|
||||||
value={watch('manufacturer_id')}
|
value={watch('manufacturer_id') || undefined}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
setValue('manufacturer_id', value);
|
setValue('manufacturer_id', value);
|
||||||
setSelectedManufacturerId(value);
|
setSelectedManufacturerId(value);
|
||||||
@@ -557,7 +557,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
<>
|
<>
|
||||||
<Combobox
|
<Combobox
|
||||||
options={rideModels}
|
options={rideModels}
|
||||||
value={watch('ride_model_id')}
|
value={watch('ride_model_id') || undefined}
|
||||||
onValueChange={(value) => setValue('ride_model_id', value)}
|
onValueChange={(value) => setValue('ride_model_id', value)}
|
||||||
placeholder="Select model"
|
placeholder="Select model"
|
||||||
searchPlaceholder="Search models..."
|
searchPlaceholder="Search models..."
|
||||||
@@ -595,7 +595,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
{/* Dates */}
|
{/* Dates */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<FlexibleDateInput
|
<FlexibleDateInput
|
||||||
value={watch('opening_date') ? parseDateOnly(watch('opening_date')) : undefined}
|
value={watch('opening_date') ? parseDateOnly(watch('opening_date')!) : undefined}
|
||||||
precision={(watch('opening_date_precision') as DatePrecision) || 'day'}
|
precision={(watch('opening_date_precision') as DatePrecision) || 'day'}
|
||||||
onChange={(date, precision) => {
|
onChange={(date, precision) => {
|
||||||
setValue('opening_date', date ? toDateOnly(date) : undefined);
|
setValue('opening_date', date ? toDateOnly(date) : undefined);
|
||||||
@@ -608,7 +608,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FlexibleDateInput
|
<FlexibleDateInput
|
||||||
value={watch('closing_date') ? parseDateOnly(watch('closing_date')) : undefined}
|
value={watch('closing_date') ? parseDateOnly(watch('closing_date')!) : undefined}
|
||||||
precision={(watch('closing_date_precision') as DatePrecision) || 'day'}
|
precision={(watch('closing_date_precision') as DatePrecision) || 'day'}
|
||||||
onChange={(date, precision) => {
|
onChange={(date, precision) => {
|
||||||
setValue('closing_date', date ? toDateOnly(date) : undefined);
|
setValue('closing_date', date ? toDateOnly(date) : undefined);
|
||||||
@@ -1390,7 +1390,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
<DialogTitle>Create New Designer</DialogTitle>
|
<DialogTitle>Create New Designer</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ManufacturerForm
|
<ManufacturerForm
|
||||||
initialData={tempNewDesigner}
|
initialData={tempNewDesigner || undefined}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
setTempNewDesigner(data);
|
setTempNewDesigner(data);
|
||||||
setIsDesignerModalOpen(false);
|
setIsDesignerModalOpen(false);
|
||||||
@@ -1413,7 +1413,7 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ManufacturerForm
|
<ManufacturerForm
|
||||||
initialData={tempNewManufacturer}
|
initialData={tempNewManufacturer || undefined}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
setTempNewManufacturer(data);
|
setTempNewManufacturer(data);
|
||||||
setSelectedManufacturerName(data.name);
|
setSelectedManufacturerName(data.name);
|
||||||
@@ -1442,9 +1442,9 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<RideModelForm
|
<RideModelForm
|
||||||
manufacturerName={selectedManufacturerName || tempNewManufacturer?.name}
|
manufacturerName={selectedManufacturerName || tempNewManufacturer?.name || ''}
|
||||||
manufacturerId={selectedManufacturerId}
|
manufacturerId={selectedManufacturerId}
|
||||||
initialData={tempNewRideModel}
|
initialData={tempNewRideModel || undefined}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
setTempNewRideModel(data);
|
setTempNewRideModel(data);
|
||||||
setIsModelModalOpen(false);
|
setIsModelModalOpen(false);
|
||||||
|
|||||||
@@ -730,7 +730,7 @@ export const SystemActivityLog = forwardRef<SystemActivityLogRef, SystemActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return <span>Unknown activity type</span>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { setAuthMethod } from '@/lib/sessionFlags';
|
|||||||
import { validateEmailNotDisposable } from '@/lib/emailValidation';
|
import { validateEmailNotDisposable } from '@/lib/emailValidation';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
|
import type { SignInOptions } from '@/types/supabase-auth';
|
||||||
|
|
||||||
interface AuthModalProps {
|
interface AuthModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -70,7 +71,7 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
|||||||
setSignInCaptchaToken(null);
|
setSignInCaptchaToken(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const signInOptions: any = {
|
const signInOptions: SignInOptions = {
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
password: formData.password,
|
password: formData.password,
|
||||||
};
|
};
|
||||||
@@ -125,7 +126,7 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
|||||||
const { handlePostAuthFlow } = await import('@/lib/authService');
|
const { handlePostAuthFlow } = await import('@/lib/authService');
|
||||||
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
const postAuthResult = await handlePostAuthFlow(data.session, 'password');
|
||||||
|
|
||||||
if (postAuthResult.success && postAuthResult.data.shouldRedirect) {
|
if (postAuthResult.success && postAuthResult.data?.shouldRedirect) {
|
||||||
// Get the TOTP factor ID
|
// Get the TOTP factor ID
|
||||||
const { data: factors } = await supabase.auth.mfa.listFactors();
|
const { data: factors } = await supabase.auth.mfa.listFactors();
|
||||||
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
const totpFactor = factors?.totp?.find(f => f.status === 'verified');
|
||||||
|
|||||||
@@ -297,8 +297,9 @@ export function SubmissionReviewManager({
|
|||||||
description: `Successfully approved ${selectedItemIds.size} item(s)${requestId ? ` (Request: ${requestId.substring(0, 8)})` : ''}`,
|
description: `Successfully approved ${selectedItemIds.size} item(s)${requestId ? ` (Request: ${requestId.substring(0, 8)})` : ''}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const successCount = data.results.filter((r: any) => r.success).length;
|
interface ApprovalResult { success: boolean; item_id: string; error?: string }
|
||||||
const failCount = data.results.filter((r: any) => !r.success).length;
|
const successCount = data.results.filter((r: ApprovalResult) => r.success).length;
|
||||||
|
const failCount = data.results.filter((r: ApprovalResult) => !r.success).length;
|
||||||
|
|
||||||
const allFailed = failCount > 0 && successCount === 0;
|
const allFailed = failCount > 0 && successCount === 0;
|
||||||
const someFailed = failCount > 0 && successCount > 0;
|
const someFailed = failCount > 0 && successCount > 0;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { supabase } from '@/integrations/supabase/client';
|
|||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
||||||
|
import type { ModerationItem } from '@/types/moderation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile data structure returned from the database
|
* Profile data structure returned from the database
|
||||||
@@ -143,7 +144,7 @@ export function useProfileCache() {
|
|||||||
* @param submissions - Array of submissions with user_id and reviewer_id
|
* @param submissions - Array of submissions with user_id and reviewer_id
|
||||||
* @returns Map of userId -> profile for all users involved
|
* @returns Map of userId -> profile for all users involved
|
||||||
*/
|
*/
|
||||||
const fetchForSubmissions = useCallback(async (submissions: any[]): Promise<Map<string, CachedProfile>> => {
|
const fetchForSubmissions = useCallback(async (submissions: ModerationItem[]): Promise<Map<string, CachedProfile>> => {
|
||||||
const userIds = submissions.map(s => s.user_id).filter(Boolean);
|
const userIds = submissions.map(s => s.user_id).filter(Boolean);
|
||||||
const reviewerIds = submissions.map(s => s.reviewer_id).filter((id): id is string => !!id);
|
const reviewerIds = submissions.map(s => s.reviewer_id).filter((id): id is string => !!id);
|
||||||
const allUserIds = [...new Set([...userIds, ...reviewerIds])];
|
const allUserIds = [...new Set([...userIds, ...reviewerIds])];
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { logger } from '@/lib/logger';
|
|||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
||||||
import type { RealtimeChannel, RealtimePostgresChangesPayload } from '@supabase/supabase-js';
|
import type { RealtimeChannel, RealtimePostgresChangesPayload } from '@supabase/supabase-js';
|
||||||
|
import type { Json } from '@/integrations/supabase/types';
|
||||||
import type { ModerationItem, EntityFilter, StatusFilter } from '@/types/moderation';
|
import type { ModerationItem, EntityFilter, StatusFilter } from '@/types/moderation';
|
||||||
import type { useEntityCache } from './useEntityCache';
|
import type { useEntityCache } from './useEntityCache';
|
||||||
import type { useProfileCache } from './useProfileCache';
|
import type { useProfileCache } from './useProfileCache';
|
||||||
@@ -176,7 +177,7 @@ export function useRealtimeSubscriptions(
|
|||||||
/**
|
/**
|
||||||
* Resolve entity names for a submission
|
* Resolve entity names for a submission
|
||||||
*/
|
*/
|
||||||
const resolveEntityNames = useCallback(async (submission: any) => {
|
const resolveEntityNames = useCallback(async (submission: { submission_type: string; content: Json }) => {
|
||||||
const content = submission.content as SubmissionContent;
|
const content = submission.content as SubmissionContent;
|
||||||
let entityName = content?.name || 'Unknown';
|
let entityName = content?.name || 'Unknown';
|
||||||
let parkName: string | undefined;
|
let parkName: string | undefined;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import type { User } from '@supabase/supabase-js';
|
||||||
import { useAuth } from './useAuth';
|
import { useAuth } from './useAuth';
|
||||||
import { useUserRole } from './useUserRole';
|
import { useUserRole } from './useUserRole';
|
||||||
import { useRequireMFA } from './useRequireMFA';
|
import { useRequireMFA } from './useRequireMFA';
|
||||||
@@ -15,7 +16,7 @@ export interface AdminGuardState {
|
|||||||
needsMFA: boolean;
|
needsMFA: boolean;
|
||||||
|
|
||||||
/** Current authenticated user */
|
/** Current authenticated user */
|
||||||
user: any;
|
user: User | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ export interface Park {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description?: string;
|
description?: string | null;
|
||||||
status: string; // Allow any string from database
|
status: string; // Allow any string from database
|
||||||
park_type: string; // Allow any string from database
|
park_type: string; // Allow any string from database
|
||||||
opening_date?: string;
|
opening_date?: string | null;
|
||||||
opening_date_precision?: string;
|
opening_date_precision?: string | null;
|
||||||
closing_date?: string;
|
closing_date?: string | null;
|
||||||
closing_date_precision?: string;
|
closing_date_precision?: string | null;
|
||||||
website_url?: string;
|
website_url?: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
@@ -132,7 +132,7 @@ export interface Ride {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description?: string;
|
description?: string | null;
|
||||||
park?: Park | { name: string; slug: string; location?: Location }; // Allow partial park data
|
park?: Park | { name: string; slug: string; location?: Location }; // Allow partial park data
|
||||||
ride_model?: RideModel;
|
ride_model?: RideModel;
|
||||||
manufacturer?: Company;
|
manufacturer?: Company;
|
||||||
@@ -140,10 +140,10 @@ export interface Ride {
|
|||||||
category: string; // Allow any string from database
|
category: string; // Allow any string from database
|
||||||
ride_sub_type?: string; // Sub-category like "Flying Coaster", "Inverted Coaster", etc.
|
ride_sub_type?: string; // Sub-category like "Flying Coaster", "Inverted Coaster", etc.
|
||||||
status: string; // Allow any string from database
|
status: string; // Allow any string from database
|
||||||
opening_date?: string;
|
opening_date?: string | null;
|
||||||
opening_date_precision?: string;
|
opening_date_precision?: string | null;
|
||||||
closing_date?: string;
|
closing_date?: string | null;
|
||||||
closing_date_precision?: string;
|
closing_date_precision?: string | null;
|
||||||
height_requirement?: number;
|
height_requirement?: number;
|
||||||
age_requirement?: number;
|
age_requirement?: number;
|
||||||
capacity_per_hour?: number;
|
capacity_per_hour?: number;
|
||||||
|
|||||||
@@ -164,6 +164,9 @@ export interface ModerationItem {
|
|||||||
reviewed_at?: string;
|
reviewed_at?: string;
|
||||||
|
|
||||||
/** ID of the moderator who reviewed this item */
|
/** ID of the moderator who reviewed this item */
|
||||||
|
reviewer_id?: string;
|
||||||
|
|
||||||
|
/** Username of the moderator who reviewed this item */
|
||||||
reviewed_by?: string;
|
reviewed_by?: string;
|
||||||
|
|
||||||
/** Notes left by the reviewing moderator */
|
/** Notes left by the reviewing moderator */
|
||||||
|
|||||||
24
src/types/supabase-auth.ts
Normal file
24
src/types/supabase-auth.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Extended Supabase Auth Types
|
||||||
|
* Supabase auth methods accept options objects not fully typed in official SDK
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface SignInOptions {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
options?: {
|
||||||
|
captchaToken?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignUpOptions {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
options?: {
|
||||||
|
data?: {
|
||||||
|
username?: string;
|
||||||
|
display_name?: string;
|
||||||
|
};
|
||||||
|
captchaToken?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": false,
|
"strict": true,
|
||||||
"noUnusedLocals": false,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": false,
|
"noUnusedParameters": false,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user