This commit is contained in:
69
src/lib/server/db/schema/animaldex.ts
Normal file
69
src/lib/server/db/schema/animaldex.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { doublePrecision, integer, pgTable, text } from 'drizzle-orm/pg-core';
|
||||
import { id, timestamps, timestamptz } from './helpers';
|
||||
|
||||
export const animals = pgTable('animals', {
|
||||
id: id(),
|
||||
|
||||
species: text('species').notNull(),
|
||||
breed: text('breed'),
|
||||
animalName: text('animal_name'),
|
||||
description: text('description'),
|
||||
|
||||
// AI detection stored on the animal (from the first/primary photo)
|
||||
aiBreedSuggestion: text('ai_breed_suggestion'),
|
||||
aiBreedConfidence: doublePrecision('ai_breed_confidence'),
|
||||
|
||||
// Moderation — the animal entity is moderated once.
|
||||
// Accepted = visible on map (as long as it has accepted sightings too).
|
||||
// Denied animals are hidden but not deleted.
|
||||
submittedAt: timestamptz('submitted_at').notNull().defaultNow(),
|
||||
acceptedAt: timestamptz('accepted_at'),
|
||||
deniedAt: timestamptz('denied_at'),
|
||||
...timestamps
|
||||
});
|
||||
|
||||
export const sightings = pgTable('sightings', {
|
||||
id: id(),
|
||||
animalId: integer('animal_id')
|
||||
.notNull()
|
||||
.references(() => animals.id, { onDelete: 'cascade' }),
|
||||
|
||||
reporterName: text('reporter_name'),
|
||||
|
||||
seenAt: timestamptz('seen_at').notNull(),
|
||||
lat: doublePrecision('lat').notNull(),
|
||||
lng: doublePrecision('lng').notNull(),
|
||||
|
||||
submittedAt: timestamptz('submitted_at').notNull().defaultNow(),
|
||||
acceptedAt: timestamptz('accepted_at'),
|
||||
deniedAt: timestamptz('denied_at'),
|
||||
...timestamps
|
||||
});
|
||||
|
||||
export const photos = pgTable('photos', {
|
||||
id: id(),
|
||||
sightingId: integer('sighting_id')
|
||||
.notNull()
|
||||
.references(() => sightings.id, { onDelete: 'cascade' }),
|
||||
r2Key: text('r2_key').notNull(),
|
||||
url: text('url').notNull(),
|
||||
sortOrder: integer('sort_order').notNull().default(0),
|
||||
uploadedAt: timestamptz('uploaded_at').notNull().defaultNow(),
|
||||
...timestamps
|
||||
});
|
||||
|
||||
export type Animal = typeof animals.$inferSelect;
|
||||
export type NewAnimal = typeof animals.$inferInsert;
|
||||
export type Sighting = typeof sightings.$inferSelect;
|
||||
export type NewSighting = typeof sightings.$inferInsert;
|
||||
export type Photo = typeof photos.$inferSelect;
|
||||
|
||||
export type ModerationStatus = 'pending' | 'accepted' | 'denied';
|
||||
|
||||
export function getModerationStatus(
|
||||
row: Pick<Animal | Sighting, 'acceptedAt' | 'deniedAt'>
|
||||
): ModerationStatus {
|
||||
if (row.deniedAt) return 'denied';
|
||||
if (row.acceptedAt) return 'accepted';
|
||||
return 'pending';
|
||||
}
|
||||
Reference in New Issue
Block a user