feat: full locations CRUD + legal policies in settings
Backend: - CRUD completo para countries, regions y cities - GET /settings/policy/:key — página HTML pública para políticas - GET/PATCH /settings/policies/:key — admin endpoints protegidos Admin: - /locations: árbol interactivo País → Región → Ciudad con add/edit/delete - /settings: editor de Política de Privacidad y Términos con enlace público copiable - Sidebar: Ciudades → Ubicaciones Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
5c740420e9
commit
39c4301d1b
@@ -1,6 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
|
||||
const POLICY_KEYS = ['privacy', 'terms'] as const;
|
||||
type PolicyKey = typeof POLICY_KEYS[number];
|
||||
|
||||
@Injectable()
|
||||
export class SettingsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
@@ -17,4 +20,25 @@ export class SettingsService {
|
||||
update: { value },
|
||||
});
|
||||
}
|
||||
|
||||
async getPolicy(key: string): Promise<string | null> {
|
||||
const setting = await this.prisma.settings.findUnique({ where: { key: `policy_${key}` } });
|
||||
return (setting?.value as any)?.content ?? null;
|
||||
}
|
||||
|
||||
async updatePolicy(key: PolicyKey, content: string) {
|
||||
return this.prisma.settings.upsert({
|
||||
where: { key: `policy_${key}` },
|
||||
create: { key: `policy_${key}`, value: { content } },
|
||||
update: { value: { content } },
|
||||
});
|
||||
}
|
||||
|
||||
async getPolicies() {
|
||||
const [privacy, terms] = await Promise.all([
|
||||
this.getPolicy('privacy'),
|
||||
this.getPolicy('terms'),
|
||||
]);
|
||||
return { privacy, terms };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user