feat: implement complex selection flow
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -2,7 +2,9 @@ import { requireAuth } from '@/middlewares/require-auth.middleware';
|
||||
import { createComplexHandler } from '@/modules/complex/handlers/create-complex.handler';
|
||||
import { getComplexByIdHandler } from '@/modules/complex/handlers/get-complex-by-id.handler';
|
||||
import { getComplexBySlugHandler } from '@/modules/complex/handlers/get-complex-by-slug.handler';
|
||||
import { getCurrentComplexHandler } from '@/modules/complex/handlers/get-current-complex.handler';
|
||||
import { listMyComplexesHandler } from '@/modules/complex/handlers/list-my-complexes.handler';
|
||||
import { selectComplexHandler } from '@/modules/complex/handlers/select-complex.handler';
|
||||
import { updateComplexHandler } from '@/modules/complex/handlers/update-complex.handler';
|
||||
import type { AppEnv } from '@/types/hono';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
@@ -17,6 +19,8 @@ const complexSlugParamsSchema = z.object({ slug: z.string().trim().min(1) });
|
||||
complexRoutes.use('*', requireAuth);
|
||||
|
||||
complexRoutes.post('/', zValidator('json', createComplexSchema), createComplexHandler);
|
||||
complexRoutes.get('/me', getCurrentComplexHandler);
|
||||
complexRoutes.post('/select', selectComplexHandler);
|
||||
complexRoutes.get('/mine', listMyComplexesHandler);
|
||||
complexRoutes.get(
|
||||
'/slug/:slug',
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { getCurrentComplex } from '@/modules/complex/services/complex.service';
|
||||
import type { AppContext } from '@/types/hono';
|
||||
import { getCookie } from 'hono/cookie';
|
||||
|
||||
const SELECTED_COMPLEX_COOKIE = 'selected-complex-id';
|
||||
|
||||
export async function getCurrentComplexHandler(c: AppContext) {
|
||||
const user = c.get('user');
|
||||
const complexId = getCookie(c, SELECTED_COMPLEX_COOKIE);
|
||||
|
||||
if (!complexId) {
|
||||
return c.json(null);
|
||||
}
|
||||
|
||||
const complex = await getCurrentComplex(user.id, complexId);
|
||||
|
||||
if (!complex) {
|
||||
return c.json(null);
|
||||
}
|
||||
|
||||
return c.json(complex);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { selectComplex } from '@/modules/complex/services/complex.service';
|
||||
import type { AppContext } from '@/types/hono';
|
||||
import { setCookie } from 'hono/cookie';
|
||||
import { z } from 'zod';
|
||||
|
||||
const SELECTED_COMPLEX_COOKIE = 'selected-complex-id';
|
||||
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
||||
|
||||
const selectComplexSchema = z.object({
|
||||
complexId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export async function selectComplexHandler(c: AppContext) {
|
||||
const user = c.get('user');
|
||||
const body = await c.req.json();
|
||||
const result = selectComplexSchema.safeParse(body);
|
||||
|
||||
if (!result.success) {
|
||||
return c.json({ message: 'Invalid payload', issues: result.error.issues }, { status: 400 });
|
||||
}
|
||||
|
||||
const { complexId } = result.data;
|
||||
const complex = await selectComplex(user.id, complexId);
|
||||
|
||||
if (!complex) {
|
||||
return c.json({ message: 'Complex not found or not associated with user' }, { status: 404 });
|
||||
}
|
||||
|
||||
setCookie(c, SELECTED_COMPLEX_COOKIE, complexId, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'strict',
|
||||
path: '/',
|
||||
maxAge: COOKIE_MAX_AGE,
|
||||
});
|
||||
|
||||
return c.json(complex);
|
||||
}
|
||||
@@ -104,7 +104,52 @@ export async function listMyComplexes(userId: string) {
|
||||
},
|
||||
});
|
||||
|
||||
return complexUsers.map((complexUser) => complexUser.complex);
|
||||
return complexUsers.map((complexUser) => ({
|
||||
...complexUser.complex,
|
||||
role: complexUser.role,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getCurrentComplex(userId: string, complexId: string) {
|
||||
const complexUser = await db.complexUser.findUnique({
|
||||
where: {
|
||||
complexId_userId: {
|
||||
complexId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
complex: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!complexUser) return null;
|
||||
|
||||
return {
|
||||
...complexUser.complex,
|
||||
role: complexUser.role,
|
||||
};
|
||||
}
|
||||
|
||||
export async function selectComplex(userId: string, complexId: string) {
|
||||
const complexUser = await db.complexUser.findUnique({
|
||||
where: {
|
||||
complexId_userId: {
|
||||
complexId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
complex: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!complexUser) return null;
|
||||
|
||||
return {
|
||||
...complexUser.complex,
|
||||
role: complexUser.role,
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateComplex(id: string, input: UpdateComplexInput) {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { getUserProfile } from '@/modules/user/services/user.service';
|
||||
import type { AppContext } from '@/types/hono';
|
||||
import { getCookie } from 'hono/cookie';
|
||||
|
||||
export function getUserProfileHandler(c: AppContext) {
|
||||
const SELECTED_COMPLEX_COOKIE = 'selected-complex-id';
|
||||
|
||||
export async function getUserProfileHandler(c: AppContext) {
|
||||
const user = c.get('user');
|
||||
const profile = getUserProfile(user);
|
||||
const complexId = getCookie(c, SELECTED_COMPLEX_COOKIE);
|
||||
const profile = await getUserProfile(user, complexId);
|
||||
return c.json(profile);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import type { User } from '@/lib/auth';
|
||||
import { db } from '@/lib/prisma';
|
||||
import type { UserProfile } from '@repo/api-contract';
|
||||
|
||||
function getGravatarUrl(email: string): string {
|
||||
@@ -7,12 +8,29 @@ function getGravatarUrl(email: string): string {
|
||||
return `https://www.gravatar.com/avatar/${hash}?d=identicon`;
|
||||
}
|
||||
|
||||
export function getUserProfile(user: User): UserProfile {
|
||||
export async function getUserProfile(user: User, complexId?: string): Promise<UserProfile> {
|
||||
let role = 'member';
|
||||
|
||||
if (complexId) {
|
||||
const complexUser = await db.complexUser.findUnique({
|
||||
where: {
|
||||
complexId_userId: {
|
||||
complexId,
|
||||
userId: user.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (complexUser) {
|
||||
role = complexUser.role.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
fullName: user.name,
|
||||
email: user.email,
|
||||
role: (user as any).role || 'member',
|
||||
role,
|
||||
avatarUrl: user.image || getGravatarUrl(user.email),
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user