diff --git a/apps/app/languine.lock b/apps/app/languine.lock index 8b4b0e8dec..688b365ad8 100644 --- a/apps/app/languine.lock +++ b/apps/app/languine.lock @@ -122,12 +122,23 @@ files: theme.options.system: a45da96d0bf6575970f2d27af22be28a sidebar.overview: 3b878279a04dc47d60932cb294d96259 sidebar.policies: 9e476387322a5c250893cf9c5c4ce78c - sidebar.risk: 59ca88f7b0e80cdd9af330af600a9ff6 + sidebar.risk: 7228bb53bb7855d458965d2f15fc6cd7 sidebar.vendors: dfcc5efe778e6340336015dc02617922 sidebar.integrations: e01aecb528730f3bfe10f9d57f1317bf sidebar.settings: f4f70727dc34561dfde1a3c529b6205c sidebar.evidence: 63b1eb1a39194d82271ec937fba19714 sidebar.people: 78386ec8f2845742c324a3d7d3e800ff + sub_pages.risk.overview: 7228bb53bb7855d458965d2f15fc6cd7 + sub_pages.risk.register: e4c28136d96146bd5fe9dfe41214138c + sub_pages.risk.risk_overview: 5226ebb7d548f2d3a8f8c4fd08851405 + sub_pages.risk.risk_comments: 354f3f4ded9791cb5e60cbef67f544a8 + sub_pages.risk.tasks.task_overview: d5a893e5bfa69efefb2667f8e7ec600c + sub_pages.policies.all: 4992678c2f629035e5c3bcde296b596a + sub_pages.policies.editor: e2c974366aff19ed493a501108cbf948 + sub_pages.people.all: 78386ec8f2845742c324a3d7d3e800ff + sub_pages.people.employee_details: 62fa24399196c3b1bcb1cf2cdf771da4 + sub_pages.settings.members: 8196446d7293bfeb288d7c21e36a1886 + sub_pages.frameworks.overview: 04fb5df59766a9852e5dd2d0430ca27e auth.title: 4b33d501b99fef8f85f32b942fcd0b1f auth.description: 1fd4b045f6d46683c611e45b8de4bcf6 auth.options: 4dab36ac83853282fc0d7bae20c19e90 @@ -144,7 +155,8 @@ files: onboarding.title: deecac09e6560d6f0f98401d9852d514 onboarding.setup: ad2376beebecdcf7846ba973fa1a005b onboarding.description: 7cd2a7692cfacbbea2045f2e6416b805 - onboarding.unavailable: c321ca4d67424a3a48aaef9053753cc4 + onboarding.fields.fullName.label: 614cffa523202658a898e34a5d94d05e + onboarding.fields.fullName.placeholder: df1fc96e5401396fe01e24363a9ec40d onboarding.fields.name.label: c1ca926603dc454ba981aa514db8402b onboarding.fields.name.placeholder: 0ad99cd46646d542668f0f40ab982477 onboarding.fields.subdomain.label: beed05bccb8b6f21466910eb4a4f142b @@ -153,6 +165,9 @@ files: onboarding.fields.website.placeholder: 4ebd8773cbf5dc2531d6b28b6fe32a26 onboarding.success: 13ff66cec7127e895b2e463771341c13 onboarding.error: 9e78ff392dee43a6c78a8c4e29ff4dc2 + onboarding.check_availability: 118740af1c4521b917e29791d661db82 + onboarding.available: 78945de8de090e90045d299651a68a9b + onboarding.unavailable: 453e6aa38d87b28ccae545967c53004f overview.title: 3b878279a04dc47d60932cb294d96259 overview.framework_chart.title: 9c53d5a3379ee2c9bc7c1c55f54724b9 overview.requirement_chart.title: 69d9304854b767112e32573d7eeddc24 diff --git a/apps/app/package.json b/apps/app/package.json index 3062aa1555..57bff589c8 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -10,20 +10,19 @@ "clean-react": "rm -rf node_modules/react; rm -rf node_modules/react-dom" }, "dependencies": { - "@ai-sdk/anthropic": "^1.1.6", - "@ai-sdk/google": "^1.1.8", - "@ai-sdk/openai": "^1.1.9", - "@browserbasehq/sdk": "^2.2.0", + "@ai-sdk/anthropic": "^1.1.7", + "@ai-sdk/google": "^1.1.12", + "@browserbasehq/sdk": "^2.3.0", "@bubba/notifications": "workspace:*", "@date-fns/tz": "^1.2.0", "@hookform/resolvers": "^3.10.0", "@nangohq/frontend": "^0.48.4", "@nangohq/node": "^0.48.4", - "@novu/headless": "^2.0.4", + "@novu/headless": "^2.6.5", "@novu/react": "^2.6.5", - "@prisma/instrumentation": "^6.3.0", + "@prisma/instrumentation": "^6.3.1", "@tanstack/react-query": "^5.66.0", - "@tanstack/react-table": "^8.20.6", + "@tanstack/react-table": "^8.21.2", "@tiptap/extension-bullet-list": "^2.11.5", "@tiptap/extension-heading": "^2.11.5", "@tiptap/extension-list-item": "^2.11.5", @@ -38,32 +37,32 @@ "@trigger.dev/react-hooks": "3.3.13", "@trigger.dev/sdk": "3.3.13", "@types/xml2js": "^0.4.14", - "@uploadthing/react": "^7.1.5", + "@uploadthing/react": "^7.2.0", "@upstash/ratelimit": "^2.0.5", - "ai": "^4.1.16", + "ai": "^4.1.37", "argon2": "^0.41.1", "bun": "^1.2.2", "crypto": "^1.0.1", - "dub": "^0.46.21", + "dub": "^0.46.29", "framer-motion": "^11.18.2", "geist": "^1.3.1", "highlight.js": "^11.11.1", - "ky": "^1.7.4", - "languine": "^3.0.1", - "marked": "^15.0.6", - "next": "^15.1.6", + "ky": "^1.7.5", + "languine": "^3.0.4", + "marked": "^15.0.7", + "next": "^15.1.7", "next-auth": "^5.0.0-beta.25", "next-international": "^1.3.1", "next-intl": "^3.26.3", - "next-safe-action": "^7.10.2", + "next-safe-action": "^7.10.3", "next-themes": "^0.4.4", "novel": "^1.0.2", - "novu": "^2.2.2", + "novu": "^2.6.5", "nuqs": "^2.3.2", "playwright-core": "^1.50.1", - "posthog-js": "^1.215.3", - "posthog-node": "^4.4.1", - "puppeteer-core": "^24.1.1", + "posthog-js": "^1.217.2", + "posthog-node": "^4.5.2", + "puppeteer-core": "^24.2.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-hook-form": "^7.54.2", @@ -72,14 +71,15 @@ "react-markdown": "^9.0.3", "react-textarea-autosize": "^8.5.7", "react-use-draggable-scroll": "^0.4.7", - "remark-gfm": "^4.0.0", + "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", - "resend": "^4.1.1", + "resend": "^4.1.2", "sonner": "^1.7.4", "stripe": "^17.6.0", + "tiptap-extension-global-drag-handle": "^0.1.17", "tiptap-markdown": "^0.8.10", "ts-pattern": "^5.6.2", - "uploadthing": "^7.4.4", + "uploadthing": "^7.5.0", "use-debounce": "^10.0.4", "use-long-press": "^3.2.0", "xml2js": "^0.6.2", @@ -89,10 +89,10 @@ "devDependencies": { "@bubba/db": "workspace:*", "@trigger.dev/build": "3.3.13", - "@types/node": "^22.13.0", + "@types/node": "^22.13.2", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "postcss": "^8.5.1", + "postcss": "^8.5.2", "tailwindcss": "^3.4.17", "typescript": "^5.7.3" } diff --git a/apps/app/public/fonts/GeneralSans-Variable.ttf b/apps/app/public/fonts/GeneralSans-Variable.ttf new file mode 100644 index 0000000000..65b0dabc1b Binary files /dev/null and b/apps/app/public/fonts/GeneralSans-Variable.ttf differ diff --git a/apps/app/public/fonts/GeneralSans-VariableItalic.ttf b/apps/app/public/fonts/GeneralSans-VariableItalic.ttf new file mode 100644 index 0000000000..e9450be74c Binary files /dev/null and b/apps/app/public/fonts/GeneralSans-VariableItalic.ttf differ diff --git a/apps/app/src/actions/ai/assistant-settings-action.ts b/apps/app/src/actions/ai/assistant-settings-action.ts deleted file mode 100644 index 1ac2a13cfb..0000000000 --- a/apps/app/src/actions/ai/assistant-settings-action.ts +++ /dev/null @@ -1,30 +0,0 @@ -"use server"; - -import { revalidatePath } from "next/cache"; -import { authActionClient } from "../safe-action"; -import { assistantSettingsSchema } from "../schema"; -import { getAssistantSettings, setAssistantSettings } from "./storage"; - -export const assistantSettingsAction = authActionClient - .schema(assistantSettingsSchema) - .metadata({ - name: "assistant-settings", - }) - .action(async ({ parsedInput: params, ctx: { user } }) => { - const settings = await getAssistantSettings(); - - if (!user?.organizationId || !user?.id) { - throw new Error("User not found"); - } - - await setAssistantSettings({ - settings, - params, - userId: user.id, - organizationId: user.organizationId, - }); - - revalidatePath("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/account/assistant"); - - return params; - }); diff --git a/apps/app/src/actions/ai/chat/get-chats-action.ts b/apps/app/src/actions/ai/chat/get-chats-action.ts deleted file mode 100644 index 28d1ff1dd2..0000000000 --- a/apps/app/src/actions/ai/chat/get-chats-action.ts +++ /dev/null @@ -1,43 +0,0 @@ -"use server"; - -import { addMonths, addWeeks, isAfter, isBefore, isToday } from "date-fns"; -import { getChats } from "../storage"; -import type { Chat } from "../types"; - -export async function getChatsAction() { - const data = await getChats(); - - if (!data.length) { - return []; - } - - const base: { "1d": Chat[]; "7d": Chat[]; "30d": Chat[] } = { - "1d": [], - "7d": [], - "30d": [], - }; - - for (const obj of data) { - const currentDate = new Date(obj.createdAt); - - if (isToday(currentDate)) { - base["1d"].push(obj); - } - - if ( - !isToday(currentDate) && - isBefore(currentDate, addWeeks(currentDate, 1)) - ) { - base["7d"].push(obj); - } - - if ( - isAfter(currentDate, addWeeks(currentDate, 1)) && - isBefore(currentDate, addMonths(currentDate, 1)) - ) { - base["30d"].push(obj); - } - } - - return base; -} diff --git a/apps/app/src/actions/ai/chat/index.tsx b/apps/app/src/actions/ai/chat/index.tsx deleted file mode 100644 index ae3c82d359..0000000000 --- a/apps/app/src/actions/ai/chat/index.tsx +++ /dev/null @@ -1,181 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import { BotMessage, SpinnerMessage } from "@/components/chat/messages"; -import { openai } from "@ai-sdk/openai"; -import { client as RedisClient } from "@bubba/kv"; -import { Ratelimit } from "@upstash/ratelimit"; -import { - createAI, - createStreamableValue, - getMutableAIState, - streamUI, -} from "ai/rsc"; -import { startOfMonth, subMonths } from "date-fns"; -import { nanoid } from "nanoid"; -import { headers } from "next/headers"; -import { getAssistantSettings, saveChat } from "../storage"; -import type { AIState, Chat, ClientMessage, UIState } from "../types"; - -const ratelimit = new Ratelimit({ - limiter: Ratelimit.fixedWindow(10, "10s"), - redis: RedisClient, -}); - -export async function submitUserMessage( - content: string, -): Promise { - "use server"; - const headerList = await headers(); - - const ip = headerList.get("x-forwarded-for"); - const session = await auth(); - - const { success } = await ratelimit.limit(ip ?? ""); - - const aiState = getMutableAIState(); - - if (!success) { - aiState.update({ - ...aiState.get(), - messages: [ - ...aiState.get().messages, - { - id: nanoid(), - role: "assistant", - content: - "Not so fast, tiger. You've reached your message limit. Please wait a minute and try again.", - }, - ], - }); - - return { - id: nanoid(), - role: "assistant", - display: ( - - ), - }; - } - - const user = session?.user; - const organizationId = user?.organizationId as string; - - const defaultValues = { - from: subMonths(startOfMonth(new Date()), 12).toISOString(), - to: new Date().toISOString(), - }; - - aiState.update({ - ...aiState.get(), - messages: [ - ...aiState.get().messages, - { - id: nanoid(), - role: "user", - content, - }, - ], - }); - - let textStream: undefined | ReturnType>; - let textNode: undefined | React.ReactNode; - - const result = await streamUI({ - model: openai("gpt-4o-mini"), - initial: , - system: `\ - You are a helpful assistant in Midday who can help users ask questions about their transactions, revenue, spending find invoices and more. - - If the user wants the burn rate, call \`getBurnRate\` function. - If the user wants the runway, call \`getRunway\` function. - If the user wants the profit, call \`getProfit\` function. - If the user wants to find transactions or expenses, call \`getTransactions\` function. - If the user wants to see spending based on a category, call \`getSpending\` function. - If the user wants to find invoices or receipts, call \`getInvoices\` function. - If the user wants to find documents, call \`getDocuments\` function. - Don't return markdown, just plain text. - - Always try to call the functions with default values, otherwise ask the user to respond with parameters. - Current date is: ${new Date().toISOString().split("T")[0]} \n - `, - messages: [ - ...aiState.get().messages.map((message: any) => ({ - role: message.role, - content: message.content, - name: message.name, - display: null, - })), - ], - text: ({ content, done, delta }) => { - if (!textStream) { - textStream = createStreamableValue(""); - textNode = ; - } - - if (done) { - textStream.done(); - aiState.done({ - ...aiState.get(), - messages: [ - ...aiState.get().messages, - { - id: nanoid(), - role: "assistant", - content, - }, - ], - }); - } else { - textStream.update(delta); - } - - return textNode; - }, - tools: {}, - }); - - return { - id: nanoid(), - role: "assistant", - display: result.value, - }; -} - -export async function handleAIStateChange(state: AIState, done: boolean) { - "use server"; - - const settings = await getAssistantSettings(); - - if (!done || !settings?.enabled) return; - - const createdAt = new Date(); - const userId = state.user.id; - const organizationId = state.user.organizationId; - - const { chatId, messages } = state; - - const firstMessageContent = messages?.at(0)?.content ?? ""; - const title = - typeof firstMessageContent === "string" - ? firstMessageContent.substring(0, 100) - : ""; - - const chat: Chat = { - id: chatId, - title, - userId, - createdAt, - messages, - organizationId, - }; - - await saveChat(chat); -} - -export const AI = createAI({ - actions: { - submitUserMessage, - }, - initialUIState: [], -}); diff --git a/apps/app/src/actions/ai/chat/utils.tsx b/apps/app/src/actions/ai/chat/utils.tsx deleted file mode 100644 index 9273dfac1e..0000000000 --- a/apps/app/src/actions/ai/chat/utils.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { BotMessage, UserMessage } from "@/components/chat/messages"; -import type { Chat } from "../types"; - -export const sleep = (ms: number) => - new Promise((resolve) => setTimeout(resolve, ms)); - -function getUIComponentFromMessage(message: any) { - if (message.role === "user") { - return {message.content}; - } - - if (message.role === "assistant" && typeof message.content === "string") { - return ; - } - - if (message.role === "tool") { - return message.content.map((tool: any) => { - switch (tool.toolName) { - default: - return null; - } - }); - } -} - -export const getUIStateFromAIState = (aiState: Chat) => { - return aiState?.messages - .filter((message) => message.role !== "system") - .map((message, index) => ({ - id: `${aiState.id}-${index}`, - display: getUIComponentFromMessage(message), - })); -}; diff --git a/apps/app/src/actions/ai/clear-history-action.ts b/apps/app/src/actions/ai/clear-history-action.ts deleted file mode 100644 index e1c8f33807..0000000000 --- a/apps/app/src/actions/ai/clear-history-action.ts +++ /dev/null @@ -1,19 +0,0 @@ -"use server"; - -import { authActionClient } from "../safe-action"; -import { clearChats } from "./storage"; - -export const clearHistoryAction = authActionClient - .metadata({ - name: "clear-history", - }) - .action(async ({ ctx: { user } }) => { - if (!user?.organizationId || !user?.id) { - throw new Error("User not found"); - } - - return clearChats({ - organizationId: user.organizationId, - userId: user.id, - }); - }); diff --git a/apps/app/src/actions/ai/editor/generate-editor-content.ts b/apps/app/src/actions/ai/editor/generate-editor-content.ts deleted file mode 100644 index 066abb0975..0000000000 --- a/apps/app/src/actions/ai/editor/generate-editor-content.ts +++ /dev/null @@ -1,50 +0,0 @@ -"use server"; - -import { openai } from "@ai-sdk/openai"; -import { streamText } from "ai"; -import { createStreamableValue } from "ai/rsc"; - -type Params = { - input: string; - context?: string; -}; - -export async function generateEditorContent({ input, context }: Params) { - const stream = createStreamableValue(""); - - (async () => { - const { textStream } = await streamText({ - model: openai("gpt-4o-mini"), - prompt: input, - temperature: 0.8, - system: ` - You are an expert AI assistant specializing in invoice-related content generation and improvement. Your task is to enhance or modify invoice text based on specific instructions. Follow these guidelines: - - 1. Language: Always respond in the same language as the input prompt. - 2. Conciseness: Keep responses brief and precise, with a maximum of 200 characters. - - You will perform one of these primary functions: - - Fix grammar: Rectify any grammatical errors while preserving the original meaning. - - Improve text: Refine the text to improve clarity and professionalism. - - Condense text: Remove any unnecessary text and only keep the invoice-related content and make it more concise. - - Format your response as plain text, using '\n' for line breaks when necessary. - Do not include any titles or headings in your response. - Provide only invoice-relevant content without any extraneous information. - Begin your response directly with the relevant invoice text or information. - - For custom prompts, maintain focus on invoice-related content. Ensure all generated text is appropriate for formal business communications and adheres to standard invoice practices. - Current date is: ${new Date().toISOString().split("T")[0]} \n - ${context} -`, - }); - - for await (const delta of textStream) { - stream.update(delta); - } - - stream.done(); - })(); - - return { output: stream.value }; -} diff --git a/apps/app/src/actions/ai/session.ts b/apps/app/src/actions/ai/session.ts deleted file mode 100644 index 250ed6ecb5..0000000000 --- a/apps/app/src/actions/ai/session.ts +++ /dev/null @@ -1,18 +0,0 @@ -"use server"; - -import { - closeBrowserSession, - createSession, - getSessionUrl, -} from "@/lib/operator/session"; - -export async function createAndGetSessionUrl() { - const session = await createSession(); - const url = await getSessionUrl(session.id); - - return { sessionId: session.id, url }; -} - -export async function closeSession(sessionId: string) { - await closeBrowserSession(sessionId); -} \ No newline at end of file diff --git a/apps/app/src/actions/ai/storage.ts b/apps/app/src/actions/ai/storage.ts deleted file mode 100644 index ac8b89cbd4..0000000000 --- a/apps/app/src/actions/ai/storage.ts +++ /dev/null @@ -1,165 +0,0 @@ -"use server"; - -import { auth } from "@/auth"; -import type { Chat, SettingsResponse } from "./types"; - -import { Redis } from "@upstash/redis"; - -const redis = new Redis({ - url: process.env.UPSTASH_REDIS_REST_URL!, - token: process.env.UPSTASH_REDIS_REST_TOKEN!, -}); - -export async function getAssistantSettings(): Promise { - const session = await auth(); - const user = session?.user; - - const organizationId = user?.organizationId; - const userId = user?.id; - - const defaultSettings: SettingsResponse = { - enabled: true, - }; - - const settings = await redis.get( - `assistant:${organizationId}:user:${userId}:settings`, - ); - - return { - ...defaultSettings, - ...(settings || {}), - }; -} - -type SetAassistant = { - settings: SettingsResponse; - userId: string; - organizationId: string; - params: { - enabled?: boolean | undefined; - }; -}; - -export async function setAssistantSettings({ - settings, - params, - userId, - organizationId, -}: SetAassistant) { - return redis.set(`assistant:${organizationId}:user:${userId}:settings`, { - ...settings, - ...params, - }); -} - -export async function clearChats({ - organizationId, - userId, -}: { organizationId: string; userId: string }) { - const chats: string[] = await redis.zrange( - `chat:${organizationId}:user:${userId}`, - 0, - -1, - ); - - const pipeline = redis.pipeline(); - - for (const chat of chats) { - pipeline.del(chat); - pipeline.zrem(`chat:${organizationId}:user:${userId}`, chat); - } - - await pipeline.exec(); -} - -export async function getLatestChat() { - const settings = await getAssistantSettings(); - if (!settings?.enabled) return null; - - const session = await auth(); - const user = session?.user; - - const organizationId = user?.organizationId; - const userId = user?.id; - - try { - const chat: string[] = await redis.zrange( - `chat:${organizationId}:user:${userId}`, - 0, - 1, - { - rev: true, - }, - ); - - const lastId = chat.at(0); - - if (lastId) { - return redis.hgetall(lastId); - } - } catch (error) { - return null; - } -} - -export async function getChats() { - const session = await auth(); - const user = session?.user; - - const organizationId = user?.organizationId; - const userId = user?.id; - - try { - const pipeline = redis.pipeline(); - const chats: string[] = await redis.zrange( - `chat:${organizationId}:user:${userId}`, - 0, - -1, - { - rev: true, - }, - ); - - for (const chat of chats) { - pipeline.hgetall(chat); - } - - const results = await pipeline.exec(); - - return results as Chat[]; - } catch (error) { - return []; - } -} - -export async function getChat(id: string) { - const session = await auth(); - const user = session?.user; - - const userId = user?.id; - - const chat = await redis.hgetall(`chat:${id}`); - - if (!chat || (userId && chat.userId !== userId)) { - return null; - } - - return chat; -} - -export async function saveChat(chat: Chat) { - const pipeline = redis.pipeline(); - pipeline.hmset(`chat:${chat.id}`, chat); - - const chatKey = `chat:${chat.organizationId}:user:${chat.userId}`; - - pipeline - .zadd(chatKey, { - score: Date.now(), - member: `chat:${chat.id}`, - }) - // Expire in 30 days - .expire(chatKey, 2592000); - - await pipeline.exec(); -} diff --git a/apps/app/src/actions/ai/types.ts b/apps/app/src/actions/ai/types.ts deleted file mode 100644 index d0bc90e279..0000000000 --- a/apps/app/src/actions/ai/types.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { CoreMessage } from "ai"; -import type { ReactNode } from "react"; - -export type Message = CoreMessage & { - id: string; -}; - -export interface Chat extends Record { - id: string; - title: string; - createdAt: Date; - userId: string; - organizationId: string; - messages: Message[]; -} - -export type SettingsResponse = { - enabled: boolean; -}; - -export type User = { - id: string; - organizationId: string; - full_name: string; - avatar_url: string; -}; - -export type AIState = { - chatId: string; - user: User; - messages: Message[]; -}; - -export type UIState = { - id: string; - display: React.ReactNode; -}[]; - -export interface ServerMessage { - role: "user" | "assistant" | "tool"; - content: string; -} - -export interface ClientMessage { - id: string; - role: "user" | "assistant"; - display: ReactNode; -} - -type ValueOrUpdater = T | ((prevState: T) => T); - -export type MutableAIState = { - get: () => AIState; - update: (newState: ValueOrUpdater) => void; - done: ((newState: AIState) => void) | (() => void); -}; diff --git a/apps/app/src/actions/schema.ts b/apps/app/src/actions/schema.ts index 424af452c7..784e84f9ef 100644 --- a/apps/app/src/actions/schema.ts +++ b/apps/app/src/actions/schema.ts @@ -9,6 +9,7 @@ import { import { z } from "zod"; export const organizationSchema = z.object({ + fullName: z.string().min(1, "Full name is required"), name: z.string().min(1, "Name is required"), website: z.string().url("Must be a valid URL"), subdomain: z.string().min(1, "Subdomain is required").optional(), diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/layout.tsx index e3156ac366..1c4bb2f821 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/layout.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/layout.tsx @@ -9,7 +9,7 @@ export default async function Layout({ const t = await getI18n(); return ( -
+
{children}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/page.tsx index fb8a78672c..af7767adac 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/page.tsx @@ -1,5 +1,29 @@ +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { FrameworksOverview } from "./Components/FrameworksOverview"; -export default function DashboardPage() { +export default async function DashboardPage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); + return ; } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.overview"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/layout.tsx deleted file mode 100644 index 513df54dfb..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/layout.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { getI18n } from "@/locales/server"; -import { SecondaryMenu } from "@bubba/ui/secondary-menu"; - -export default async function Layout({ - children, -}: { - children: React.ReactNode; -}) { - const t = await getI18n(); - - return ( -
- - -
{children}
-
- ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/page.tsx deleted file mode 100644 index 0028ee0da0..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence-tasks/(overview)/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { auth } from "@/auth"; -import { Browser } from "@/components/browser/browser"; -import { redirect } from "next/navigation"; - -export default async function RiskManagement() { - const session = await auth(); - - if (!session?.user?.organizationId) { - redirect("/onboarding"); - } - - return ( -
- -
- ); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/page.tsx index f1e66f3914..2d319dd765 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/page.tsx @@ -2,7 +2,10 @@ import { auth } from "@/auth"; import { FrameworkControls } from "@/components/frameworks/framework-controls"; import { FrameworkOverview } from "@/components/frameworks/framework-overview"; import { SkeletonLoader } from "@/components/skeleton-loader"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; import { Suspense } from "react"; @@ -10,12 +13,14 @@ import { Suspense } from "react"; interface PageProps { params: Promise<{ frameworkId: string; + locale: string; }>; } export default async function FrameworkPage({ params }: PageProps) { const session = await auth(); - const { frameworkId } = await params; + const { frameworkId, locale } = await params; + setStaticParamsLocale(locale); if (!session?.user?.organizationId) { redirect("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/login"); @@ -65,7 +70,7 @@ const getFramework = unstable_cache( ["framework-cache"], { tags: ["framework-cache"], - } + }, ); const getOrganizationFramework = unstable_cache( @@ -88,7 +93,7 @@ const getOrganizationFramework = unstable_cache( ["org-framework-cache"], { tags: ["org-framework-cache"], - } + }, ); const getFrameworkCategories = unstable_cache( @@ -130,5 +135,19 @@ const getFrameworkCategories = unstable_cache( ["framework-categories-cache"], { tags: ["framework-categories-cache"], - } + }, ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string; frameworkId: string }>; +}): Promise { + const { locale, frameworkId } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: `${t("sub_pages.frameworks.overview")}`, + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/integrations/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/integrations/page.tsx index f2581c7735..cbb34cb36d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/integrations/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/integrations/page.tsx @@ -1,22 +1,23 @@ import { auth } from "@/auth"; -import { DeleteOrganization } from "@/components/forms/organization/delete-organization"; -import { UpdateOrganizationName } from "@/components/forms/organization/update-organization-name"; -import { UpdateOrganizationWebsite } from "@/components/forms/organization/update-organization-website"; import { IntegrationsHeader } from "@/components/integrations/integrations-header"; import { IntegrationsServer } from "@/components/integrations/integrations.server"; import { SkeletonLoader } from "@/components/skeleton-loader"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { redirect } from "next/navigation"; import { Suspense } from "react"; -export const metadata: Metadata = { - title: "Integrations | Comp AI", -}; +export default async function IntegrationsPage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); -export default async function OrganizationSettings() { const session = await auth(); - const [organization] = await Promise.all([ db.organization.findUnique({ where: { @@ -39,3 +40,17 @@ export default async function OrganizationSettings() {
); } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.integrations"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/people/[employeeId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/people/[employeeId]/page.tsx index 23d7faa5a6..1b043cc3d1 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/people/[employeeId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/people/[employeeId]/page.tsx @@ -1,12 +1,18 @@ import { auth } from "@/auth"; +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { redirect } from "next/navigation"; import { EmployeeDetails } from "./components/EmployeeDetails"; export default async function EmployeeDetailsPage({ params, }: { - params: Promise<{ employeeId: string }>; + params: Promise<{ locale: string; employeeId: string }>; }) { + const { locale, employeeId } = await params; + setStaticParamsLocale(locale); + const session = await auth(); const organizationId = session?.user.organizationId; @@ -14,7 +20,20 @@ export default async function EmployeeDetailsPage({ redirect("/"); } - const { employeeId } = await params; - return ; } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string; employeeId: string }>; +}): Promise { + const { locale } = await params; + + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.people.employee_details"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/people/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/people/page.tsx index ab1f80f66b..f189e85333 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/people/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/people/page.tsx @@ -1,9 +1,19 @@ import { auth } from "@/auth"; import { getServerColumnHeaders } from "@/components/tables/people/server-columns"; +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { redirect } from "next/navigation"; import { EmployeesList } from "./components/EmployeesList"; -export default async function PeoplePage() { +export default async function PeoplePage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); + const session = await auth(); const organizationId = session?.user.organizationId; @@ -15,3 +25,18 @@ export default async function PeoplePage() { return ; } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.people"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/page.tsx index 1c77f38fd9..cab6584e5f 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/page.tsx @@ -1,8 +1,18 @@ import { auth } from "@/auth"; +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { redirect } from "next/navigation"; -import { PoliciesOverview } from "./Components/PoliciesOverview"; +import { PoliciesOverview } from "./components/PoliciesOverview"; + +export default async function PoliciesOverviewPage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); -export default async function PoliciesOverviewPage() { const session = await auth(); if (!session?.user?.organizationId) { @@ -11,3 +21,17 @@ export default async function PoliciesOverviewPage() { return ; } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.policies"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/Actions/publish-policy.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/Actions/publish-policy.ts index 246cd11317..ead1296cdb 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/Actions/publish-policy.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/Actions/publish-policy.ts @@ -1,7 +1,7 @@ "use server"; import { authActionClient } from "@/actions/safe-action"; -import { db, type OrganizationPolicy } from "@bubba/db"; +import { type OrganizationPolicy, db } from "@bubba/db"; import { z } from "zod"; const schema = z.object({ diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx index b257dd6e28..0687651fd8 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx @@ -1,11 +1,29 @@ import { PolicyOverview } from "@/components/policies/policy-overview"; +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; interface PageProps { - params: Promise<{ id: string }>; + params: Promise<{ locale: string; id: string }>; } export default async function PolicyPage({ params }: PageProps) { - const { id } = await params; + const { locale, id } = await params; + setStaticParamsLocale(locale); return ; } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string; id: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.policies.editor"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx index 23760713fe..bf1190604c 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx @@ -10,7 +10,7 @@ export default async function Layout({ const t = await getI18n(); return ( -
+
Loading...
}> ; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); -export default async function PoliciesPage() { const session = await auth(); if (!session?.user?.organizationId) { @@ -42,3 +52,17 @@ export default async function PoliciesPage() { ); } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string; id: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.policies.all"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicies.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicies.ts index c17eb70250..d13a075842 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicies.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicies.ts @@ -1,8 +1,8 @@ "use client"; -import { getPolicies } from "../Actions/get-policies"; -import useSWR from "swr"; import type { OrganizationPolicy } from "@bubba/db"; +import useSWR from "swr"; +import { getPolicies } from "../actions/get-policies"; const POLICIES_OVERVIEW_KEY = "policies-overview"; @@ -10,7 +10,7 @@ async function fetchPolicies(): Promise { const response = await getPolicies({}); if (!response?.data?.success || !response.data.data) { - throw new Error(response?.data?.error || "Failed to fetch policy data"); + throw new Error(response?.data?.error || "Failed to fetch policy"); } return response.data.data; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicy.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicy.ts index 67b16b622a..5369fbb06b 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicy.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/hooks/usePolicy.ts @@ -1,8 +1,8 @@ "use client"; -import { getPolicy } from "../Actions/get-policy"; -import useSWR from "swr"; import type { OrganizationPolicy, Policy } from "@bubba/db"; +import useSWR from "swr"; +import { getPolicy } from "../actions/get-policy"; const POLICY_KEY = "policy"; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/(overview)/page.tsx index a36fd68894..931ea81b10 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/(overview)/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/(overview)/page.tsx @@ -1,11 +1,21 @@ import { auth } from "@/auth"; import { RiskOverview } from "@/components/risks/charts/risk-overview"; import { RisksByAssignee } from "@/components/risks/charts/risks-by-assignee"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; -export default async function RiskManagement() { +export default async function RiskManagement({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); + const session = await auth(); if (!session?.user?.organizationId) { @@ -96,3 +106,17 @@ const getRiskOverview = unstable_cache( }, ["risk-overview-cache"], ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.risk"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/comments/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/comments/page.tsx index 1c815a2c2f..9db344e507 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/comments/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/comments/page.tsx @@ -1,6 +1,9 @@ import { auth } from "@/auth"; import { RiskComments } from "@/components/risks/risk-comments"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; @@ -67,3 +70,17 @@ const getUsers = unstable_cache( }, ["users-cache"], ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.risk.risk_comments"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/page.tsx index 009eb5b2aa..09fd07d15e 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/page.tsx @@ -14,6 +14,8 @@ import { getServerColumnHeaders } from "@/components/tables/risk-tasks/server-co import { getI18n } from "@/locales/server"; import { type RiskTaskStatus, db } from "@bubba/db"; import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; @@ -25,7 +27,7 @@ interface PageProps { page?: string; per_page?: string; }>; - params: Promise<{ riskId: string }>; + params: Promise<{ riskId: string; locale: string }>; } export default async function RiskPage({ searchParams, params }: PageProps) { @@ -232,3 +234,17 @@ const getUsers = unstable_cache( }, ["users-cache"], ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.risk.risk_overview"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/tasks/[taskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/tasks/[taskId]/page.tsx index 2e9b0fe96e..adda350454 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/tasks/[taskId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/[riskId]/tasks/[taskId]/page.tsx @@ -4,7 +4,10 @@ import { TaskComment } from "@/components/risks/tasks/task-comments"; import { TaskOverview } from "@/components/risks/tasks/task-overview"; import { env } from "@/env.mjs"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; @@ -110,3 +113,17 @@ const getUsers = unstable_cache( }, ["users-cache"], ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.risk.tasks.task_overview"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/register/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/register/page.tsx index b410831fae..4181aff8f3 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/risk/register/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/risk/register/page.tsx @@ -11,11 +11,17 @@ import { import { FilterToolbar } from "@/components/tables/risk-register/filter-toolbar"; import { Loading } from "@/components/tables/risk-register/loading"; import { getServerColumnHeaders } from "@/components/tables/risk-register/server-columns"; +import { getI18n } from "@/locales/server"; import { type Departments, type RiskStatus, db } from "@bubba/db"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; -interface PageProps { +export default async function RiskRegisterPage({ + searchParams, +}: { + params: Promise<{ locale: string }>; searchParams: Promise<{ search?: string; category?: string; @@ -25,9 +31,7 @@ interface PageProps { page?: string; per_page?: string; }>; -} - -export default async function RiskRegisterPage({ searchParams }: PageProps) { +}) { const session = await auth(); const organizationId = session?.user.organizationId; const columnHeaders = await getServerColumnHeaders(); @@ -178,3 +182,17 @@ const getRisks = unstable_cache( }, ["risks-cache"], ); + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.risk.register"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/page.tsx index f9dbba63c0..969b924054 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/page.tsx @@ -1,9 +1,33 @@ import { TeamMembers } from "@/components/settings/team/team-members"; +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; + +export default async function Members({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); -export default async function Members() { return (
); } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sub_pages.settings.members"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx index bb82533d57..63836d9aa2 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx @@ -2,15 +2,20 @@ import { auth } from "@/auth"; import { DeleteOrganization } from "@/components/forms/organization/delete-organization"; import { UpdateOrganizationName } from "@/components/forms/organization/update-organization-name"; import { UpdateOrganizationWebsite } from "@/components/forms/organization/update-organization-website"; +import { getI18n } from "@/locales/server"; import { db } from "@bubba/db"; import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; import { redirect } from "next/navigation"; -export const metadata: Metadata = { - title: "Organization Settings | Comp AI", -}; +export default async function OrganizationSettings({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); -export default async function OrganizationSettings() { const session = await auth(); const [organization] = await Promise.all([ @@ -38,3 +43,17 @@ export default async function OrganizationSettings() {
); } + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.settings"), + }; +} diff --git a/apps/app/src/app/[locale]/layout.tsx b/apps/app/src/app/[locale]/layout.tsx index 04eb1848f4..1e7317405c 100644 --- a/apps/app/src/app/[locale]/layout.tsx +++ b/apps/app/src/app/[locale]/layout.tsx @@ -8,6 +8,7 @@ import { GeistMono } from "geist/font/mono"; import { GeistSans } from "geist/font/sans"; import type { Metadata } from "next"; import { SessionProvider } from "next-auth/react"; +import localFont from "next/font/local"; import { NuqsAdapter } from "nuqs/adapters/next/app"; import { Toaster } from "sonner"; import { extractRouterConfig } from "uploadthing/server"; @@ -67,8 +68,14 @@ export const viewport = { ], }; -export const preferredRegion = ["fra1", "sfo1", "iad1"]; -export const maxDuration = 60; +const font = localFont({ + src: "/../../../public/fonts/GeneralSans-Variable.ttf", + display: "swap", + variable: "--font-general-sans", +}); + +export const preferredRegion = ["auto"]; +export const maxDuration = 5; if (env.NEXT_PUBLIC_POSTHOG_KEY && env.NEXT_PUBLIC_POSTHOG_HOST) { initializeServer({ @@ -91,7 +98,7 @@ export default async function Layout(props: { diff --git a/apps/app/src/app/api/chat/route.ts b/apps/app/src/app/api/chat/route.ts index 0a9026695b..0100487924 100644 --- a/apps/app/src/app/api/chat/route.ts +++ b/apps/app/src/app/api/chat/route.ts @@ -14,7 +14,6 @@ import { } from "ai"; import { z } from "zod"; import { - clickableElementsPrompt, getCachedMessages, } from "./lib/prompts"; import { diff --git a/apps/app/src/components/assistant/assistant-modal.tsx b/apps/app/src/components/assistant/assistant-modal.tsx deleted file mode 100644 index c5556f4cea..0000000000 --- a/apps/app/src/components/assistant/assistant-modal.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { useAssistantStore } from "@/store/assistant"; -import { Dialog, DialogContent } from "@bubba/ui/dialog"; -import { useHotkeys } from "react-hotkeys-hook"; -import { Assistant } from "."; - -export function AssistantModal() { - const { isOpen, setOpen } = useAssistantStore(); - - useHotkeys("meta+k", () => setOpen(true), { - enableOnFormTags: true, - }); - - return ( - - - - - - ); -} diff --git a/apps/app/src/components/assistant/button.tsx b/apps/app/src/components/assistant/button.tsx deleted file mode 100644 index 67b24a74ed..0000000000 --- a/apps/app/src/components/assistant/button.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { useAssistantStore } from "@/store/assistant"; -import { Button } from "@bubba/ui/button"; - -export function AssistantButton() { - const { setOpen } = useAssistantStore(); - - return ( - - ); -} diff --git a/apps/app/src/components/assistant/feedback.tsx b/apps/app/src/components/assistant/feedback.tsx deleted file mode 100644 index 2c22f32d13..0000000000 --- a/apps/app/src/components/assistant/feedback.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { sendFeebackAction } from "@/actions/send-feedback-action"; -import { Button } from "@bubba/ui/button"; -import { Icons } from "@bubba/ui/icons"; -import { Textarea } from "@bubba/ui/textarea"; -import { Loader2 } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useState } from "react"; - -type Props = { - onClose: () => void; -}; - -export function AssistantFeedback({ onClose }: Props) { - const [value, setValue] = useState(""); - - const action = useAction(sendFeebackAction, { - onSuccess: () => { - setValue(""); - }, - }); - - return ( -
-
- -

Send Feedback

-
-
- {action.status === "hasSucceeded" ? ( -
-

Thank you for your feedback!

-

- We will be back with you as soon as possible -

-
- ) : ( -
-