feat: add trip invitation creation and acceptance flow
This commit is contained in:
91
backend/libs/trips/src/trip-invitations.repository.ts
Normal file
91
backend/libs/trips/src/trip-invitations.repository.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import type { Kysely } from 'kysely';
|
||||
import { KYSELY_DB } from '../../database/src';
|
||||
import type { Database } from '../../database/src';
|
||||
import type { CreateTripInvitationFields, TripInvitation } from './trip.types';
|
||||
|
||||
function toTripInvitation(row: {
|
||||
id: string;
|
||||
trip_id: string;
|
||||
email: string;
|
||||
invited_by_user_id: string;
|
||||
token_hash: string;
|
||||
expires_at: Date;
|
||||
accepted_at: Date | null;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
}): TripInvitation {
|
||||
return {
|
||||
id: row.id,
|
||||
tripId: row.trip_id,
|
||||
email: row.email,
|
||||
invitedByUserId: row.invited_by_user_id,
|
||||
tokenHash: row.token_hash,
|
||||
expiresAt: row.expires_at,
|
||||
acceptedAt: row.accepted_at,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class TripInvitationsRepository {
|
||||
constructor(@Inject(KYSELY_DB) private readonly db: Kysely<Database>) {}
|
||||
|
||||
async create(
|
||||
tripId: string,
|
||||
fields: CreateTripInvitationFields,
|
||||
): Promise<TripInvitation> {
|
||||
const row = await this.db
|
||||
.insertInto('trip_invitations')
|
||||
.values({
|
||||
trip_id: tripId,
|
||||
email: fields.email,
|
||||
invited_by_user_id: fields.invitedByUserId,
|
||||
token_hash: fields.tokenHash,
|
||||
expires_at: fields.expiresAt.toISOString(),
|
||||
})
|
||||
.returningAll()
|
||||
.executeTakeFirstOrThrow();
|
||||
return toTripInvitation(row);
|
||||
}
|
||||
|
||||
async findByTokenHash(
|
||||
tokenHash: string,
|
||||
): Promise<TripInvitation | undefined> {
|
||||
const row = await this.db
|
||||
.selectFrom('trip_invitations')
|
||||
.selectAll()
|
||||
.where('token_hash', '=', tokenHash)
|
||||
.executeTakeFirst();
|
||||
return row ? toTripInvitation(row) : undefined;
|
||||
}
|
||||
|
||||
async listByTrip(tripId: string): Promise<TripInvitation[]> {
|
||||
const rows = await this.db
|
||||
.selectFrom('trip_invitations')
|
||||
.selectAll()
|
||||
.where('trip_id', '=', tripId)
|
||||
.execute();
|
||||
return rows.map(toTripInvitation);
|
||||
}
|
||||
|
||||
async markAccepted(invitationId: string): Promise<void> {
|
||||
await this.db
|
||||
.updateTable('trip_invitations')
|
||||
.set({
|
||||
accepted_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
.where('id', '=', invitationId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
async remove(tripId: string, invitationId: string): Promise<void> {
|
||||
await this.db
|
||||
.deleteFrom('trip_invitations')
|
||||
.where('trip_id', '=', tripId)
|
||||
.where('id', '=', invitationId)
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user