107 lines
2.3 KiB
TypeScript
107 lines
2.3 KiB
TypeScript
import { Prisma, Sport } from '@/generated/prisma/client';
|
|
import { Errors } from '@/lib/errors';
|
|
import { db } from '@/lib/prisma';
|
|
import { Result, err, ok } from '@/lib/result';
|
|
import { v7 as uuidv7 } from 'uuid';
|
|
|
|
export type CreateSportInput = {
|
|
name: string;
|
|
};
|
|
|
|
export type UpdateSportInput = {
|
|
name?: string;
|
|
isActive?: boolean;
|
|
};
|
|
|
|
function slugify(value: string): string {
|
|
return value
|
|
.normalize('NFD')
|
|
.replace(/[\u0300-\u036f]/g, '')
|
|
.toLowerCase()
|
|
.trim()
|
|
.replace(/[^a-z0-9\s-]/g, '')
|
|
.replace(/\s+/g, '-')
|
|
.replace(/-+/g, '-');
|
|
}
|
|
|
|
async function buildUniqueSlug(source: string, excludeSportId?: string): Promise<string> {
|
|
const base = slugify(source);
|
|
const fallback = base.length > 0 ? base : `sport-${uuidv7().slice(0, 8)}`;
|
|
|
|
let candidate = fallback;
|
|
let index = 1;
|
|
|
|
while (true) {
|
|
const existing = await db.sport.findFirst({
|
|
where: {
|
|
slug: candidate,
|
|
...(excludeSportId
|
|
? {
|
|
id: {
|
|
not: excludeSportId,
|
|
},
|
|
}
|
|
: {}),
|
|
},
|
|
select: { id: true },
|
|
});
|
|
|
|
if (!existing) return candidate;
|
|
|
|
index += 1;
|
|
candidate = `${fallback}-${index}`;
|
|
}
|
|
}
|
|
|
|
export async function listSports(): Promise<Result<Sport[]>> {
|
|
const sports = await db.sport.findMany({
|
|
orderBy: { name: 'asc' },
|
|
});
|
|
return ok(sports);
|
|
}
|
|
|
|
export async function createSport(input: CreateSportInput) {
|
|
const slug = await buildUniqueSlug(input.name);
|
|
|
|
const existing = await db.sport.count({
|
|
where: { slug },
|
|
});
|
|
|
|
if (existing > 0) {
|
|
return err(Errors.conflict('Ya existe un deporte con ese nombre.'));
|
|
}
|
|
|
|
const created = await db.sport.create({
|
|
data: {
|
|
id: uuidv7(),
|
|
name: input.name.trim(),
|
|
slug,
|
|
isActive: true,
|
|
},
|
|
});
|
|
|
|
return ok(created);
|
|
}
|
|
|
|
export async function getSportById(id: string) {
|
|
return db.sport.findUnique({ where: { id } });
|
|
}
|
|
|
|
export async function updateSport(id: string, input: UpdateSportInput) {
|
|
const data: Prisma.SportUncheckedUpdateInput = {};
|
|
|
|
if (input.name) {
|
|
data.name = input.name;
|
|
data.slug = await buildUniqueSlug(input.name, id);
|
|
}
|
|
|
|
if (input.isActive !== undefined) {
|
|
data.isActive = input.isActive;
|
|
}
|
|
|
|
return db.sport.update({
|
|
where: { id },
|
|
data,
|
|
});
|
|
}
|