diff --git a/apps/client/index.html b/apps/client/index.html index e4528b7c..98e02c8b 100644 --- a/apps/client/index.html +++ b/apps/client/index.html @@ -2,7 +2,8 @@ - + + Docmost diff --git a/apps/client/public/favicon-16x16.png b/apps/client/public/favicon-16x16.png new file mode 100644 index 00000000..6298fe8a Binary files /dev/null and b/apps/client/public/favicon-16x16.png differ diff --git a/apps/client/public/favicon-32x32.png b/apps/client/public/favicon-32x32.png new file mode 100644 index 00000000..40d6a30e Binary files /dev/null and b/apps/client/public/favicon-32x32.png differ diff --git a/apps/client/src/components/common/recent-changes.tsx b/apps/client/src/components/common/recent-changes.tsx index 8dedb261..055629b2 100644 --- a/apps/client/src/components/common/recent-changes.tsx +++ b/apps/client/src/components/common/recent-changes.tsx @@ -64,7 +64,7 @@ export default function RecentChanges({ spaceId }: Props) { ) : ( - No records to show + No pages yet ); } diff --git a/apps/client/src/components/layouts/global/top-menu.tsx b/apps/client/src/components/layouts/global/top-menu.tsx index 07e87f12..7c82f231 100644 --- a/apps/client/src/components/layouts/global/top-menu.tsx +++ b/apps/client/src/components/layouts/global/top-menu.tsx @@ -29,10 +29,11 @@ export default function TopMenu() { - diff --git a/apps/client/src/features/auth/components/login-form.tsx b/apps/client/src/features/auth/components/login-form.tsx index 92b2c8fa..9433b1af 100644 --- a/apps/client/src/features/auth/components/login-form.tsx +++ b/apps/client/src/features/auth/components/login-form.tsx @@ -1,22 +1,17 @@ import * as React from "react"; import * as z from "zod"; - import { useForm, zodResolver } from "@mantine/form"; import useAuth from "@/features/auth/hooks/use-auth"; import { ILogin } from "@/features/auth/types/auth.types"; import { Container, Title, - Anchor, TextInput, Button, - Text, PasswordInput, Box, } from "@mantine/core"; -import { Link, useNavigate } from "react-router-dom"; import classes from "./auth.module.css"; -import { useEffect, useState } from "react"; import { useRedirectIfAuthenticated } from "@/features/auth/hooks/use-redirect-if-authenticated.ts"; const formSchema = z.object({ diff --git a/apps/client/src/features/space/components/create-space-form.tsx b/apps/client/src/features/space/components/create-space-form.tsx new file mode 100644 index 00000000..29fe46f2 --- /dev/null +++ b/apps/client/src/features/space/components/create-space-form.tsx @@ -0,0 +1,110 @@ +import { Group, Box, Button, TextInput, Stack, Textarea } from "@mantine/core"; +import React, { useEffect } from "react"; +import { useForm, zodResolver } from "@mantine/form"; +import * as z from "zod"; +import { useNavigate } from "react-router-dom"; +import { useCreateSpaceMutation } from "@/features/space/queries/space-query.ts"; +import { computeSpaceSlug } from "@/lib"; +import { getSpaceUrl } from "@/lib/config.ts"; + +const formSchema = z.object({ + name: z.string().min(2).max(50), + slug: z + .string() + .min(2) + .max(50) + .regex( + /^[a-zA-Z0-9]+$/, + "Space slug must be alphanumeric. No special characters", + ), + description: z.string().max(500), +}); +type FormValues = z.infer; + +export function CreateSpaceForm() { + const createSpaceMutation = useCreateSpaceMutation(); + const navigate = useNavigate(); + + const form = useForm({ + validate: zodResolver(formSchema), + validateInputOnChange: ["slug"], + initialValues: { + name: "", + slug: "", + description: "", + }, + }); + + useEffect(() => { + const name = form.values.name; + const words = name.trim().split(/\s+/); + + // Check if the last character is a space or if the last word is a single character (indicating it's in progress) + const lastChar = name[name.length - 1]; + const lastWordIsIncomplete = + words.length > 1 && words[words.length - 1].length === 1; + + if (lastChar !== " " || lastWordIsIncomplete) { + const slug = computeSpaceSlug(name); + form.setFieldValue("slug", slug); + } + }, [form.values.name]); + + const handleSubmit = async (data: { + name?: string; + slug?: string; + description?: string; + }) => { + const spaceData = { + name: data.name, + slug: data.slug, + description: data.description, + }; + + const createdSpace = await createSpaceMutation.mutateAsync(spaceData); + navigate(getSpaceUrl(createdSpace.slug)); + }; + + return ( + <> + +
handleSubmit(values))}> + + + + + +