Notification UI and house invitation

This commit is contained in:
2026-02-19 19:16:26 +07:00
parent 84ed1e6c21
commit fa689ea4aa
35 changed files with 2592 additions and 112 deletions

View File

@@ -1,19 +1,20 @@
import { prisma } from '@/db';
import { OrganizationWhereInput } from '@/generated/prisma/models';
import { DB_TABLE, LOG_ACTION } from '@/types/enum';
import { DB_TABLE, LOG_ACTION, NOTIFICATION_TYPE } from '@/types/enum';
import { auth } from '@lib/auth';
import { parseError } from '@lib/errors';
import { authMiddleware } from '@lib/middleware';
import { createServerFn } from '@tanstack/react-start';
import { getRequestHeaders } from '@tanstack/react-start/server';
import {
actionInvitationSchema,
baseHouse,
houseCreateBESchema,
houseEditBESchema,
houseListSchema,
invitationCreateBESchema,
} from './house.schema';
import { createAuditLog } from './repository';
import { createAuditLog, createNotification } from './repository';
export const getAllHouse = createServerFn({ method: 'GET' })
.middleware([authMiddleware])
@@ -266,12 +267,31 @@ export const invitationMember = createServerFn({ method: 'POST' })
organizationId: data.houseId,
};
const cuser = await prisma.user.findUnique({
where: { email: data.email },
});
const chouse = await prisma.organization.findUnique({
where: { id: data.houseId },
});
const result = await auth.api.createInvitation({
body,
headers,
});
if (result) {
if (result && cuser && chouse) {
await createNotification({
type: NOTIFICATION_TYPE.INVITATION,
userId: cuser.id,
title: 'INVITATION_HOUSE',
message: 'INVITATION_HOUSE',
link: result.id,
metadata: JSON.stringify({
house: chouse,
}),
readAt: null,
});
await createAuditLog({
action: LOG_ACTION.CREATE,
tableName: DB_TABLE.INVITATION,
@@ -302,6 +322,81 @@ export const cancelInvitation = createServerFn({ method: 'POST' })
},
headers,
});
if (result) {
const notification = await prisma.notification.findFirst({
where: { link: data.id },
});
if (notification) {
await prisma.notification.update({
where: { id: notification.id },
data: { link: null },
});
}
}
return result;
} catch (error) {
console.error(error);
const { message, code } = parseError(error);
throw { message, code };
}
});
export const acceptInvitation = createServerFn({ method: 'POST' })
.middleware([authMiddleware])
.inputValidator(actionInvitationSchema)
.handler(async ({ data }) => {
try {
const result = await prisma.invitation.update({
where: { id: data.id },
data: { status: 'accepted' },
});
if (result) {
const notify = await prisma.notification.update({
where: { id: data.notificationId },
data: { link: null },
});
await auth.api.addMember({
body: {
userId: notify.userId,
organizationId: result.organizationId,
role: (result.role as 'admin' | 'owner' | 'member') || 'member',
},
});
}
return result;
} catch (error) {
console.error(error);
const { message, code } = parseError(error);
throw { message, code };
}
});
export const rejectInvitation = createServerFn({ method: 'POST' })
.middleware([authMiddleware])
.inputValidator(actionInvitationSchema)
.handler(async ({ data }) => {
try {
const headers = getRequestHeaders();
const result = await auth.api.rejectInvitation({
body: {
invitationId: data.id,
},
headers,
});
if (result) {
await prisma.notification.update({
where: { id: data.notificationId },
data: { link: null },
});
}
return result;
} catch (error) {
console.error(error);