mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 18:31:13 -05:00
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
import { supabase } from '@/lib/supabaseClient';
|
|
import { handleError } from './errorHandler';
|
|
|
|
/**
|
|
* Generate a URL-safe slug from a name
|
|
* This is the canonical slug generation function used throughout the app
|
|
*/
|
|
export function generateSlugFromName(name: string): string {
|
|
if (!name) return '';
|
|
|
|
return name
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9\s-]/g, '') // Remove non-alphanumeric except spaces and hyphens
|
|
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
|
.replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
|
|
.replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
|
|
.trim();
|
|
}
|
|
|
|
/**
|
|
* Validate that a user has permission to edit slugs
|
|
* Only moderators should be able to manually edit slugs
|
|
*/
|
|
export function canEditSlug(isModerator: boolean): boolean {
|
|
return isModerator;
|
|
}
|
|
|
|
/**
|
|
* Ensure slug is unique by checking database and appending number if needed
|
|
*/
|
|
export async function ensureUniqueSlug(
|
|
baseSlug: string,
|
|
tableName: 'parks' | 'rides' | 'companies' | 'ride_models',
|
|
excludeId?: string
|
|
): Promise<string> {
|
|
let slug = baseSlug;
|
|
let counter = 1;
|
|
|
|
while (true) {
|
|
// Check if slug exists
|
|
let query = supabase
|
|
.from(tableName)
|
|
.select('id')
|
|
.eq('slug', slug);
|
|
|
|
// Exclude current record when editing
|
|
if (excludeId) {
|
|
query = query.neq('id', excludeId);
|
|
}
|
|
|
|
const { data, error } = await query.limit(1);
|
|
|
|
if (error) {
|
|
handleError(error, {
|
|
action: 'Check Slug Uniqueness',
|
|
metadata: { tableName, slug }
|
|
});
|
|
throw error;
|
|
}
|
|
|
|
// If no match found, slug is unique
|
|
if (!data || data.length === 0) {
|
|
return slug;
|
|
}
|
|
|
|
// Append counter and try again
|
|
counter++;
|
|
slug = `${baseSlug}-${counter}`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate and ensure unique slug in one operation
|
|
*/
|
|
export async function generateUniqueSlug(
|
|
name: string,
|
|
tableName: 'parks' | 'rides' | 'companies' | 'ride_models',
|
|
excludeId?: string
|
|
): Promise<string> {
|
|
const baseSlug = generateSlugFromName(name);
|
|
return ensureUniqueSlug(baseSlug, tableName, excludeId);
|
|
}
|