From e77b7cc1768cd5e22350daa8a211361b076e751b Mon Sep 17 00:00:00 2001 From: Sonny Date: Fri, 1 Nov 2024 17:42:40 +0100 Subject: [PATCH] feat: recreate form collection (layout + create) --- app/constants/paths.ts | 2 +- app/controllers/collections_controller.ts | 2 +- inertia/components/footer/footer.module.css | 1 + inertia/components/footer/mantine_footer.tsx | 11 +- inertia/i18n/locales/en/common.json | 18 +++ inertia/i18n/locales/fr/common.json | 18 +++ .../form/mantine_form_collection.tsx | 101 +++++++++++++++++ .../mantine/layouts/mantine_form_layout.tsx | 103 ++++++++++++++++++ inertia/pages/mantine/collections/create.tsx | 41 +++++++ 9 files changed, 292 insertions(+), 5 deletions(-) create mode 100644 inertia/mantine/components/form/mantine_form_collection.tsx create mode 100644 inertia/mantine/layouts/mantine_form_layout.tsx create mode 100644 inertia/pages/mantine/collections/create.tsx diff --git a/app/constants/paths.ts b/app/constants/paths.ts index b593040..5a8ef87 100644 --- a/app/constants/paths.ts +++ b/app/constants/paths.ts @@ -1,5 +1,5 @@ const PATHS = { - AUTHOR: 'https://www.sonny.dev/', + AUTHOR: 'https://www.sonny.dev/?utm_source=mylinks', REPO_GITHUB: 'https://github.com/Sonny93/my-links', EXTENSION: 'https://chromewebstore.google.com/detail/mylinks/agkmlplihacolkakgeccnbhphnepphma', diff --git a/app/controllers/collections_controller.ts b/app/controllers/collections_controller.ts index 39ccc18..5f55b88 100644 --- a/app/controllers/collections_controller.ts +++ b/app/controllers/collections_controller.ts @@ -36,7 +36,7 @@ export default class CollectionsController { // Create collection form async showCreatePage({ inertia, auth }: HttpContext) { const collections = await this.getCollectionsByAuthorId(auth.user!.id); - return inertia.render('collections/create', { + return inertia.render('mantine/collections/create', { disableHomeLink: collections.length === 0, }); } diff --git a/inertia/components/footer/footer.module.css b/inertia/components/footer/footer.module.css index c831eff..246d367 100644 --- a/inertia/components/footer/footer.module.css +++ b/inertia/components/footer/footer.module.css @@ -1,4 +1,5 @@ .footer { + width: 100%; margin-top: rem(40px); border-top: rem(1px) solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5)); diff --git a/inertia/components/footer/mantine_footer.tsx b/inertia/components/footer/mantine_footer.tsx index ecbafc6..700075b 100644 --- a/inertia/components/footer/mantine_footer.tsx +++ b/inertia/components/footer/mantine_footer.tsx @@ -1,9 +1,11 @@ import PATHS from '#constants/paths'; import { Link } from '@inertiajs/react'; import { route } from '@izzyjs/route/client'; -import { Anchor, Group, Image, Text } from '@mantine/core'; +import { Anchor, Group, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import ExternalLink from '~/components/common/external_link'; +import { MantineLanguageSwitcher } from '~/components/common/mantine_language_switcher'; +import { MantineThemeSwitcher } from '~/components/common/mantine_theme_switcher'; import packageJson from '../../../package.json'; import classes from './footer.module.css'; @@ -31,8 +33,6 @@ export function MantineFooter() { return (
- MyLinks's logo - {t('footer.made_by')}{' '} @@ -44,6 +44,11 @@ export function MantineFooter() { + + + + + {items} diff --git a/inertia/i18n/locales/en/common.json b/inertia/i18n/locales/en/common.json index 9f7d71a..db75931 100644 --- a/inertia/i18n/locales/en/common.json +++ b/inertia/i18n/locales/en/common.json @@ -29,6 +29,24 @@ "delete-confirm": "Confirm deletion?", "delete-description": "You must delete all links in this collection before you can delete this collection." }, + "form": { + "name": "Name", + "description": "Description", + "visibility": "Visibility", + "visibility-warning": "The content will be visible to everyone", + "create": "Create", + "update": "Update", + "delete": "Delete", + "cancel": "Cancel", + "save": "Save", + "close": "Close", + "confirm": "Confirm", + "delete-confirm": "Confirmer deletion?" + }, + "visibility": { + "private": "Privé", + "public": "Public" + }, "favorite": "Favorite", "add-favorite": "Add to favorites", "remove-favorite": "Remove from favorites", diff --git a/inertia/i18n/locales/fr/common.json b/inertia/i18n/locales/fr/common.json index 3544e9d..8431010 100644 --- a/inertia/i18n/locales/fr/common.json +++ b/inertia/i18n/locales/fr/common.json @@ -29,6 +29,24 @@ "delete-confirm": "Confirmer la suppression ?", "delete-description": "Vous devez supprimer tous les liens de cette collection avant de pouvoir supprimer cette collection" }, + "form": { + "name": "Nom", + "description": "Description", + "visibility": "Visibilité", + "visibility-warning": "Le contenu sera visible par tout le monde", + "create": "Créer", + "update": "Mettre à jour", + "delete": "Supprimer", + "cancel": "Annuler", + "save": "Sauvegarder", + "close": "Fermer", + "confirm": "Confirmer", + "delete-confirm": "Confirmer la suppression ?" + }, + "visibility": { + "private": "Privé", + "public": "Public" + }, "favorite": "Favoris", "add-favorite": "Ajouter aux favoris", "remove-favorite": "Retirer des favoris", diff --git a/inertia/mantine/components/form/mantine_form_collection.tsx b/inertia/mantine/components/form/mantine_form_collection.tsx new file mode 100644 index 0000000..ee9a6d5 --- /dev/null +++ b/inertia/mantine/components/form/mantine_form_collection.tsx @@ -0,0 +1,101 @@ +import { Visibility } from '#enums/visibility'; +import { Box, Group, SegmentedControl, Text, TextInput } from '@mantine/core'; +import { FormEvent } from 'react'; +import { useTranslation } from 'react-i18next'; +import BackToDashboard from '~/components/common/navigation/back_to_dashboard'; +import { MantineFormLayout } from '~/mantine/layouts/mantine_form_layout'; +import { Collection } from '~/types/app'; + +export type FormCollectionData = { + name: string; + description: string | null; + visibility: Visibility; + nextId?: Collection['id']; +}; + +interface FormCollectionProps { + title: string; + canSubmit: boolean; + disableHomeLink?: boolean; + data: FormCollectionData; + errors?: Record>; + disableInputs?: boolean; + submitBtnDanger?: boolean; + + setData: (name: string, value: any) => void; + handleSubmit: () => void; +} + +export default function MantineFormCollection({ + title, + canSubmit, + disableHomeLink, + data, + errors, + disableInputs = false, + submitBtnDanger = false, + + setData, + handleSubmit, +}: FormCollectionProps) { + const { t } = useTranslation('common'); + + const onSubmit = (event: FormEvent) => { + event.preventDefault(); + handleSubmit(); + }; + + return ( + + + setData('name', target.value)} + value={data.name} + disabled={disableInputs} + error={errors?.name} + mt="md" + autoFocus + required + /> + setData('description', target.value)} + value={data.description ?? undefined} + disabled={disableInputs} + error={errors?.description} + mt="md" + /> + + + {t('form.visibility')} + + + setData('visibility', value as Visibility)} + value={data.visibility} + style={{ minWidth: 'fit-content' }} + /> + {data.visibility === Visibility.PUBLIC && ( + + {t('form.visibility-warning')} + + )} + + + + + ); +} diff --git a/inertia/mantine/layouts/mantine_form_layout.tsx b/inertia/mantine/layouts/mantine_form_layout.tsx new file mode 100644 index 0000000..ecc6f80 --- /dev/null +++ b/inertia/mantine/layouts/mantine_form_layout.tsx @@ -0,0 +1,103 @@ +import { Head, Link } from '@inertiajs/react'; +import { route } from '@izzyjs/route/client'; +import { Anchor, Button, Container, Group, rem, Title } from '@mantine/core'; +import { FormEvent, PropsWithChildren } from 'react'; +import { useTranslation } from 'react-i18next'; +import { MantineFooter } from '~/components/footer/mantine_footer'; +import i18n from '~/i18n'; +import { appendCollectionId } from '~/lib/navigation'; +import BaseLayout from '~/mantine/layouts/_mantine_base_layout'; + +interface FormLayoutProps extends PropsWithChildren { + title: string; + + canSubmit: boolean; + handleSubmit: (event: FormEvent) => void; + textSubmitButton?: string; + + disableHomeLink?: boolean; + submitBtnDanger?: boolean; + collectionId?: number; +} + +function MantineFormLayout({ + title, + children, + + canSubmit, + handleSubmit, + textSubmitButton = i18n.t('common:form.create'), + + disableHomeLink = false, + submitBtnDanger = false, + collectionId, +}: FormLayoutProps) { + const { t } = useTranslation('common'); + return ( + +
+ +
+ + {title} + + {children} + + + {!disableHomeLink && ( + + {t('back-home')} + + )} + + + + +
+
+ ); +} + +const LayoutWrapper = (props: FormLayoutProps) => ( + + + +); + +export { LayoutWrapper as MantineFormLayout }; diff --git a/inertia/pages/mantine/collections/create.tsx b/inertia/pages/mantine/collections/create.tsx new file mode 100644 index 0000000..dd0e6a5 --- /dev/null +++ b/inertia/pages/mantine/collections/create.tsx @@ -0,0 +1,41 @@ +import { Visibility } from '#enums/visibility'; +import { useForm } from '@inertiajs/react'; +import { route } from '@izzyjs/route/client'; +import { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import MantineFormCollection, { + FormCollectionData, +} from '~/mantine/components/form/mantine_form_collection'; + +export default function CreateCollectionPage({ + disableHomeLink, +}: { + disableHomeLink: boolean; +}) { + const { t } = useTranslation('common'); + const { data, setData, submit, processing } = useForm({ + name: '', + description: '', + visibility: Visibility.PRIVATE, + }); + const isFormDisabled = useMemo( + () => processing || data.name.length === 0, + [processing, data] + ); + + const handleSubmit = () => { + const { method, url } = route('collection.create'); + submit(method, url); + }; + + return ( + + ); +}