diff --git a/apps/frontend/src/app/colors.scss b/apps/frontend/src/app/colors.scss index 65b8198f..c0082f70 100644 --- a/apps/frontend/src/app/colors.scss +++ b/apps/frontend/src/app/colors.scss @@ -22,7 +22,8 @@ --new-col-color: #2c2b2b; --new-menu-dots: #696868; --new-menu-hover: #fff; - --menu-shadow: 0 8px 30px 0 rgba(0, 0, 0, 0.50); + --menu-shadow: 0 8px 30px 0 rgba(0, 0, 0, 0.5); + --popup-color: rgba(65, 64, 66, 0.3); } .light { --new-bgColor: #f0f2f4; @@ -33,8 +34,8 @@ --new-boxFocused: #ebe8ff; --new-textColor: 14 14 14; --new-blockSeparator: #f2f2f4; - --new-btn-simple: #ECEEF1; - --new-btn-text: #0E0E0E; + --new-btn-simple: #eceef1; + --new-btn-text: #0e0e0e; --new-btn-primary: #612bd3; --new-ai-btn: #d82d7e; --new-box-hover: #f4f6f8; @@ -43,15 +44,19 @@ --new-table-text: #777b7f; --new-table-text-focused: #fc69ff; --new-small-strips: #191818; - --new-big-strips: #F5F7F9; - --new-col-color: #EFF1F3; + --new-big-strips: #f5f7f9; + --new-col-color: #eff1f3; --new-menu-dots: #696868; --new-menu-hover: #000; - --menu-shadow: -22px 83px 24px 0 rgba(55, 52, 75, 0.00), -14px 53px 22px 0 rgba(55, 52, 75, 0.01), -8px 30px 19px 0 rgba(55, 52, 75, 0.05), -3px 13px 14px 0 rgba(55, 52, 75, 0.09), -1px 3px 8px 0 rgba(55, 52, 75, 0.10); + --menu-shadow: -22px 83px 24px 0 rgba(55, 52, 75, 0), + -14px 53px 22px 0 rgba(55, 52, 75, 0.01), + -8px 30px 19px 0 rgba(55, 52, 75, 0.05), + -3px 13px 14px 0 rgba(55, 52, 75, 0.09), + -1px 3px 8px 0 rgba(55, 52, 75, 0.1); + --popup-color: rgba(55, 37, 97, 0.2); } } - :root { .dark { --color-primary: #0e0e0e; @@ -193,4 +198,4 @@ --color-custom55: #d5d7e1; --color-modalCustom: transparent; } -} \ No newline at end of file +} diff --git a/apps/frontend/src/app/global.scss b/apps/frontend/src/app/global.scss index fd801a0e..3b446329 100644 --- a/apps/frontend/src/app/global.scss +++ b/apps/frontend/src/app/global.scss @@ -357,6 +357,10 @@ body * { // /*right: -5rem !important;*/ //} +.trz { + transform: translateZ(0); +} + .uppy-FileInput-container { @apply cursor-pointer font-[500] flex justify-center items-center gap-[4px] text-[12px] rounded-[4px] w-[107px] h-[25px] text-textColor border-[2px]; @apply bg-customColor3 border-customColor21; @@ -672,3 +676,6 @@ html[dir='rtl'] [dir='ltr'] { } } } +.blur-xs { + filter: blur(4px); +} \ No newline at end of file diff --git a/apps/frontend/src/components/autopost/autopost.tsx b/apps/frontend/src/components/autopost/autopost.tsx index 456ffbfd..6792bc95 100644 --- a/apps/frontend/src/components/autopost/autopost.tsx +++ b/apps/frontend/src/components/autopost/autopost.tsx @@ -2,7 +2,7 @@ import React, { FC, Fragment, useCallback, useMemo, useState } from 'react'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR from 'swr'; import { Button } from '@gitroom/react/form/button'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Input } from '@gitroom/react/form/input'; import { FormProvider, useForm } from 'react-hook-form'; @@ -28,11 +28,8 @@ export const Autopost: FC = () => { const addWebhook = useCallback( (data?: any) => () => { modal.openModal({ - title: '', - withCloseButton: false, - classNames: { - modal: 'bg-transparent text-textColor', - }, + title: data ? 'Edit Autopost' : 'Add Autopost', + withCloseButton: true, children: , }); }, @@ -296,29 +293,7 @@ export const AddOrEditWebhook: FC<{ return (
-
- - - +
void) => { return useCallback(async () => { const data = await (await fetch('/integrations')).json(); modal.openModal({ - title: '', - withCloseButton: false, - classNames: { - modal: 'text-textColor', - }, - size: 'auto', - children: ( - - - - ), + title: 'Add Channel', + withCloseButton: true, + children: , }); }, []); }; @@ -349,20 +341,18 @@ export const AddProviderComponent: FC<{ await fetch(`/integrations/social/${identifier}`) ).json(); modal.openModal({ - title: '', + title: 'Web3 provider', withCloseButton: false, classNames: { modal: 'bg-transparent text-textColor', }, children: ( - - { - window.location.href = `/integrations/social/${identifier}?code=${code}&state=${newState}`; - }} - nonce={url} - /> - + { + window.location.href = `/integrations/social/${identifier}?code=${code}&state=${newState}`; + }} + nonce={url} + /> ), }); return; @@ -388,35 +378,29 @@ export const AddProviderComponent: FC<{ if (isExternal) { modal.closeAll(); modal.openModal({ - title: '', + title: 'URL', withCloseButton: false, classNames: { modal: 'bg-transparent text-textColor', }, - children: ( - - - - ), + children: , }); return; } if (customFields) { modal.closeAll(); modal.openModal({ - title: '', + title: 'Add Provider', withCloseButton: false, classNames: { modal: 'bg-transparent text-textColor', }, children: ( - - router.push(url)} - variables={customFields} - /> - + router.push(url)} + variables={customFields} + /> ), }); return; @@ -425,9 +409,7 @@ export const AddProviderComponent: FC<{ }, [] ); - const close = useCallback(() => { - modal.closeAll(); - }, []); + const showApiButton = useCallback( (identifier: string, name: string) => async () => { modal.openModal({ @@ -449,7 +431,6 @@ export const AddProviderComponent: FC<{ return (
-

{t('social', 'Social')}

{social.map((item) => (
{
{day.day === newDayjs().format('L') && ( @@ -391,7 +392,9 @@ export const CalendarColumn: FC<{ const isBeforeNow = useMemo(() => { const originalUtc = getDate.startOf('hour'); - return originalUtc.startOf('hour').isBefore(newDayjs().startOf('hour').utc()); + return originalUtc + .startOf('hour') + .isBefore(newDayjs().startOf('hour').utc()); }, [getDate, num]); const { start, stop } = useInterval( @@ -462,8 +465,10 @@ export const CalendarColumn: FC<{ : Fragment; modal.openModal({ closeOnClickOutside: false, + removeLayout: true, closeOnEscape: false, withCloseButton: false, + askClose: true, classNames: { modal: 'w-[100%] max-w-[1400px] text-textColor', }, @@ -515,28 +520,24 @@ export const CalendarColumn: FC<{ ? undefined : await new Promise((resolve) => { modal.openModal({ - title: '', + title: t('select_set', 'Select a Set'), closeOnClickOutside: true, + askClose: true, closeOnEscape: true, - withCloseButton: false, + withCloseButton: true, onClose: () => resolve('exit'), - classNames: { - modal: 'text-textColor', - }, children: ( - - { - resolve(selectedSet); - modal.closeAll(); - }} - onContinueWithoutSet={() => { - resolve(undefined); - modal.closeAll(); - }} - /> - + { + resolve(selectedSet); + modal.closeAll(); + }} + onContinueWithoutSet={() => { + resolve(undefined); + modal.closeAll(); + }} + /> ), }); }); @@ -547,6 +548,8 @@ export const CalendarColumn: FC<{ closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, + removeLayout: true, + askClose: true, classNames: { modal: 'w-[100%] max-w-[1400px] text-textColor', }, @@ -586,17 +589,14 @@ export const CalendarColumn: FC<{ const openStatistics = useCallback( (id: string) => () => { modal.openModal({ + title: t('statistics', 'Statistics'), closeOnClickOutside: true, closeOnEscape: true, withCloseButton: false, classNames: { modal: 'w-[100%] max-w-[1400px]', }, - children: ( - - - - ), + children: , size: '80%', // title: `Adding posts for ${getDate.format('DD/MM/YYYY HH:mm')}`, }); diff --git a/apps/frontend/src/components/launches/comments/comment.component.tsx b/apps/frontend/src/components/launches/comments/comment.component.tsx index ead064c8..1f771e23 100644 --- a/apps/frontend/src/components/launches/comments/comment.component.tsx +++ b/apps/frontend/src/components/launches/comments/comment.component.tsx @@ -1,7 +1,7 @@ import { FC, useCallback, useEffect, useState } from 'react'; import dayjs from 'dayjs'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Textarea } from '@gitroom/react/form/textarea'; import { Button } from '@gitroom/react/form/button'; import clsx from 'clsx'; diff --git a/apps/frontend/src/components/launches/customer.modal.tsx b/apps/frontend/src/components/launches/customer.modal.tsx index 5113863a..53e47716 100644 --- a/apps/frontend/src/components/launches/customer.modal.tsx +++ b/apps/frontend/src/components/launches/customer.modal.tsx @@ -1,6 +1,6 @@ import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import React, { FC, useCallback, useEffect, useState } from 'react'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Integration } from '@prisma/client'; import { Autocomplete } from '@mantine/core'; import useSWR from 'swr'; diff --git a/apps/frontend/src/components/launches/generator/generator.tsx b/apps/frontend/src/components/launches/generator/generator.tsx index 4d39fea7..97a4e0d8 100644 --- a/apps/frontend/src/components/launches/generator/generator.tsx +++ b/apps/frontend/src/components/launches/generator/generator.tsx @@ -2,7 +2,7 @@ import React, { FC, useCallback, useMemo, useState } from 'react'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { useRouter } from 'next/navigation'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'; import { classValidatorResolver } from '@hookform/resolvers/class-validator'; import { GeneratorDto } from '@gitroom/nestjs-libraries/dtos/generator/generator.dto'; @@ -153,6 +153,8 @@ const FirstStep: FC = (props) => { closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, + removeLayout: true, + askClose: true, classNames: { modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor', }, @@ -301,7 +303,7 @@ export const GeneratorComponent = () => { return; } modal.openModal({ - title: '', + title: 'Generate Posts', withCloseButton: false, classNames: { modal: 'bg-transparent text-textColor', @@ -309,9 +311,7 @@ export const GeneratorComponent = () => { size: 'xl', children: ( - - - + ), }); diff --git a/apps/frontend/src/components/launches/helpers/media.settings.component.tsx b/apps/frontend/src/components/launches/helpers/media.settings.component.tsx index 2a0531e8..3ce19f2c 100644 --- a/apps/frontend/src/components/launches/helpers/media.settings.component.tsx +++ b/apps/frontend/src/components/launches/helpers/media.settings.component.tsx @@ -213,7 +213,9 @@ export const CreateThumbnail: FC<{
- -
-
-
- - setAltText(e.target.value)} - placeholder="Describe the image/video content..." - className="w-full px-3 py-2 bg-fifth border border-tableBorder rounded-lg text-textColor placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-forth focus:border-transparent" - /> -
- {media?.path.indexOf('mp4') > -1 && ( - <> - {/* Alt Text Input */} -
- {!isEditingThumbnail ? ( -
- {/* Show existing thumbnail if it exists */} - {(newThumbnail || thumbnail) && ( -
- - Current Thumbnail: - - Current thumbnail -
- )} +
+
+ + setAltText(e.target.value)} + placeholder="Describe the image/video content..." + className="w-full px-3 py-2 bg-fifth border border-tableBorder rounded-lg text-textColor placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-forth focus:border-transparent" + /> +
+ {media?.path.indexOf('mp4') > -1 && ( + <> + {/* Alt Text Input */} +
+ {!isEditingThumbnail ? ( +
+ {/* Show existing thumbnail if it exists */} + {(newThumbnail || thumbnail) && ( +
+ + Current Thumbnail: + + Current thumbnail +
+ )} - {/* Action Buttons */} -
- - {(thumbnail || newThumbnail) && ( - - )} -
-
- ) : ( -
- {/* Back button */} -
- -
- - {/* Thumbnail Editor */} - { - // Convert blob to base64 or handle as needed - const reader = new FileReader(); - reader.onload = () => { - // You can handle the result here - for now just call onSelect with the blob URL - const url = URL.createObjectURL(blob); - setNewThumbnail(url); - setThumbnailTimestamp(timestampMs); - setIsEditingThumbnail(false); - }; - reader.readAsDataURL(blob); - }} - media={media} - altText={altText} - onAltTextChange={setAltText} - /> -
+ {/* Action Buttons */} +
+ + {(thumbnail || newThumbnail) && ( + )}
- - )} +
+ ) : ( +
+ {/* Back button */} +
+ +
- {!isEditingThumbnail && ( -
- - + {/* Thumbnail Editor */} + { + // Convert blob to base64 or handle as needed + const reader = new FileReader(); + reader.onload = () => { + // You can handle the result here - for now just call onSelect with the blob URL + const url = URL.createObjectURL(blob); + setNewThumbnail(url); + setThumbnailTimestamp(timestampMs); + setIsEditingThumbnail(false); + }; + reader.readAsDataURL(blob); + }} + media={media} + altText={altText} + onAltTextChange={setAltText} + />
)}
+ + )} + + {!isEditingThumbnail && ( +
+ +
-
+ )}
); }; diff --git a/apps/frontend/src/components/launches/menu/menu.tsx b/apps/frontend/src/components/launches/menu/menu.tsx index 202a5a2d..836d3575 100644 --- a/apps/frontend/src/components/launches/menu/menu.tsx +++ b/apps/frontend/src/components/launches/menu/menu.tsx @@ -11,7 +11,7 @@ import { useClickOutside } from '@mantine/hooks'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useToaster } from '@gitroom/react/toaster/toaster'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TimeTable } from '@gitroom/frontend/components/launches/time.table'; import { Integrations, @@ -137,18 +137,12 @@ export const Menu: FC<{ (integration) => integration.id === id ); modal.openModal({ - classNames: { - modal: 'w-[100%] max-w-[600px] bg-transparent text-textColor', - }, - size: '100%', withCloseButton: false, closeOnEscape: false, closeOnClickOutside: false, - children: ( - - - - ), + askClose: true, + title: 'Time Table Slots', + children: , }); setShow(false); }, [integrations]); @@ -175,6 +169,8 @@ export const Menu: FC<{ closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, + removeLayout: true, + askClose: true, classNames: { modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor', }, @@ -254,40 +250,36 @@ export const Menu: FC<{ classNames: { modal: 'md', }, - title: '', + title: 'Move / Add to customer', withCloseButton: false, closeOnEscape: true, closeOnClickOutside: true, children: ( - - { - mutate(); - toast.show('Customer Updated', 'success'); - }} - /> - + { + mutate(); + toast.show('Customer Updated', 'success'); + }} + /> ), }); setShow(false); }, [integrations]); const updateCredentials = useCallback(() => { modal.openModal({ - title: '', + title: 'Custom URL', withCloseButton: false, classNames: { modal: 'md', }, children: ( - - router.push(url)} - variables={findIntegration.customFields} - /> - + router.push(url)} + variables={findIntegration.customFields} + /> ), }); }, []); diff --git a/apps/frontend/src/components/launches/new.post.tsx b/apps/frontend/src/components/launches/new.post.tsx index 652c0880..457e325e 100644 --- a/apps/frontend/src/components/launches/new.post.tsx +++ b/apps/frontend/src/components/launches/new.post.tsx @@ -1,5 +1,5 @@ import React, { useCallback } from 'react'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import dayjs from 'dayjs'; import { useCalendar } from '@gitroom/frontend/components/launches/calendar.context'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; @@ -21,7 +21,7 @@ export const NewPost = () => { ? undefined : await new Promise((resolve) => { modal.openModal({ - title: '', + title: t('select_set', 'Select a Set'), closeOnClickOutside: true, closeOnEscape: true, withCloseButton: false, @@ -30,19 +30,17 @@ export const NewPost = () => { modal: 'text-textColor', }, children: ( - - { - resolve(selectedSet); - modal.closeAll(); - }} - onContinueWithoutSet={() => { - resolve(undefined); - modal.closeAll(); - }} - /> - + { + resolve(selectedSet); + modal.closeAll(); + }} + onContinueWithoutSet={() => { + resolve(undefined); + modal.closeAll(); + }} + /> ), }); }); @@ -53,6 +51,8 @@ export const NewPost = () => { closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, + removeLayout: true, + askClose: true, classNames: { modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor', }, diff --git a/apps/frontend/src/components/launches/polonto.tsx b/apps/frontend/src/components/launches/polonto.tsx index 86c49fe9..38bd3ff5 100644 --- a/apps/frontend/src/components/launches/polonto.tsx +++ b/apps/frontend/src/components/launches/polonto.tsx @@ -56,10 +56,12 @@ const ActionControls = ({ store }: any) => { body: formData, }) ).json(); - close.setMedia([{ - id: data.id, - path: data.path, - }]); + close.setMedia([ + { + id: data.id, + path: data.path, + }, + ]); close.close(); }} > @@ -102,63 +104,34 @@ const Polonto: FC<{ }; }, []); return ( -
-
-
-
- -
- -
-
- closeModal(), - setMedia, - }} - > - + closeModal(), + setMedia, + }} + > + + + + + + - - - - - - - - - - -
-
+ /> + + + + +
); }; diff --git a/apps/frontend/src/components/launches/settings.modal.tsx b/apps/frontend/src/components/launches/settings.modal.tsx index f4e35caa..c54e7333 100644 --- a/apps/frontend/src/components/launches/settings.modal.tsx +++ b/apps/frontend/src/components/launches/settings.modal.tsx @@ -1,6 +1,6 @@ import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import React, { FC, useCallback, useState } from 'react'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Integration } from '@prisma/client'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { Button } from '@gitroom/react/form/button'; diff --git a/apps/frontend/src/components/launches/statistics.tsx b/apps/frontend/src/components/launches/statistics.tsx index d4680033..d5d7c2a7 100644 --- a/apps/frontend/src/components/launches/statistics.tsx +++ b/apps/frontend/src/components/launches/statistics.tsx @@ -1,5 +1,5 @@ import React, { FC, Fragment, useCallback } from 'react'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import useSWR from 'swr'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/launches/time.table.tsx b/apps/frontend/src/components/launches/time.table.tsx index e5b98f36..e7ba35de 100644 --- a/apps/frontend/src/components/launches/time.table.tsx +++ b/apps/frontend/src/components/launches/time.table.tsx @@ -10,7 +10,7 @@ import timezone from 'dayjs/plugin/timezone'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; // @ts-ignore import useKeypress from 'react-use-keypress'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { sortBy } from 'lodash'; import { usePreventWindowUnload } from '@gitroom/react/helpers/use.prevent.window.unload'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/launches/web3/providers/nostr.provider.tsx b/apps/frontend/src/components/launches/web3/providers/nostr.provider.tsx index 5a44eb59..45deac21 100644 --- a/apps/frontend/src/components/launches/web3/providers/nostr.provider.tsx +++ b/apps/frontend/src/components/launches/web3/providers/nostr.provider.tsx @@ -5,7 +5,7 @@ import React, { FC, useMemo, useState, useCallback, useEffect } from 'react'; import { Web3ProviderInterface } from '@gitroom/frontend/components/launches/web3/web3.provider.interface'; import { useVariables } from '@gitroom/react/helpers/variable.context'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; import { ButtonCaster } from '@gitroom/frontend/components/auth/providers/farcaster.provider'; export const WrapcasterProvider: FC = (props) => { diff --git a/apps/frontend/src/components/launches/web3/providers/telegram.provider.tsx b/apps/frontend/src/components/launches/web3/providers/telegram.provider.tsx index 4d5c0540..a177f239 100644 --- a/apps/frontend/src/components/launches/web3/providers/telegram.provider.tsx +++ b/apps/frontend/src/components/launches/web3/providers/telegram.provider.tsx @@ -4,7 +4,7 @@ import '@neynar/react/dist/style.css'; import React, { FC, useCallback, useEffect, useRef, useState } from 'react'; import { Web3ProviderInterface } from '@gitroom/frontend/components/launches/web3/web3.provider.interface'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { timer } from '@gitroom/helpers/utils/timer'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; diff --git a/apps/frontend/src/components/launches/web3/providers/wrapcaster.provider.tsx b/apps/frontend/src/components/launches/web3/providers/wrapcaster.provider.tsx index a5db1e5f..4d6ffd9a 100644 --- a/apps/frontend/src/components/launches/web3/providers/wrapcaster.provider.tsx +++ b/apps/frontend/src/components/launches/web3/providers/wrapcaster.provider.tsx @@ -5,7 +5,7 @@ import React, { FC, useMemo, useState, useCallback, useEffect } from 'react'; import { Web3ProviderInterface } from '@gitroom/frontend/components/launches/web3/web3.provider.interface'; import { useVariables } from '@gitroom/react/helpers/variable.context'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; import { NeynarAuthButton, diff --git a/apps/frontend/src/components/layout/language.component.tsx b/apps/frontend/src/components/layout/language.component.tsx index 34b9c453..3d9bb432 100644 --- a/apps/frontend/src/components/layout/language.component.tsx +++ b/apps/frontend/src/components/layout/language.component.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { cookieName, fallbackLng, @@ -70,7 +70,7 @@ export const ChangeLanguageComponent = () => { const handleLanguageChange = (language: string) => { setCookie(language); i18next.changeLanguage(language); - modals.closeModal('change-language'); + modals.closeCurrent(); }; // Function to get language name in its native script @@ -123,16 +123,9 @@ export const LanguageComponent = () => { const t = useT(); const openModal = () => { modal.openModal({ - title: '', - withCloseButton: false, - modalId: 'change-language', - children: ( - - - - ), - size: 'lg', - centered: true, + title: t('change_language', 'Change Language'), + withCloseButton: true, + children: , }); }; return ( diff --git a/apps/frontend/src/components/layout/layout.settings.tsx b/apps/frontend/src/components/layout/layout.settings.tsx index b62e2b24..a2a3c814 100644 --- a/apps/frontend/src/components/layout/layout.settings.tsx +++ b/apps/frontend/src/components/layout/layout.settings.tsx @@ -72,6 +72,7 @@ export const LayoutSettings = ({ children }: { children: ReactNode }) => { {user.tier === 'FREE' && searchParams.get('check') && ( diff --git a/apps/frontend/src/components/layout/new-modal.tsx b/apps/frontend/src/components/layout/new-modal.tsx new file mode 100644 index 00000000..96b5c62e --- /dev/null +++ b/apps/frontend/src/components/layout/new-modal.tsx @@ -0,0 +1,371 @@ +import { create } from 'zustand'; +import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; +import { useShallow } from 'zustand/react/shallow'; +import React, { + createContext, + FC, + memo, + ReactNode, + useCallback, + useContext, + useEffect, + useMemo, +} from 'react'; +import { Button } from '@gitroom/react/form/button'; +import { useHotkeys } from 'react-hotkeys-hook'; +import clsx from 'clsx'; +import { EventEmitter } from 'events'; + +interface OpenModalInterface { + title?: string; + closeOnClickOutside?: boolean; + removeLayout?: boolean; + closeOnEscape?: boolean; + withCloseButton?: boolean; + askClose?: boolean; + onClose?: () => void; + children: ReactNode | ((close: () => void) => ReactNode); + classNames?: { + modal?: string; + }; + size?: string | number; + height?: string | number; + id?: string; +} + +interface ModalManagerStoreInterface { + closeById(id: string): void; + openModal(params: OpenModalInterface): void; + closeAll(): void; +} + +interface State extends ModalManagerStoreInterface { + modalManager: Array<{ id: string } & OpenModalInterface>; +} + +const useModalStore = create((set) => ({ + modalManager: [], + openModal: (params) => + set((state) => ({ + modalManager: [ + ...state.modalManager, + { id: params.id || makeId(20), ...params }, + ], + })), + closeById: (id) => + set((state) => ({ + modalManager: state.modalManager.filter((modal) => modal.id !== id), + })), + closeAll: () => set({ modalManager: [] }), +})); + +const CurrentModalContext = createContext({ id: '' }); + +interface ModalManagerInterface extends ModalManagerStoreInterface { + closeCurrent(): void; +} + +export const useModals = () => { + const { closeAll, openModal, closeById } = useModalStore( + useShallow((state) => ({ + openModal: state.openModal, + closeById: state.closeById, + closeAll: state.closeAll, + })) + ); + + const modalContext = useContext(CurrentModalContext); + + return { + openModal, + closeAll, + closeById, + closeCurrent: () => { + if (modalContext.id) { + closeById(modalContext.id); + } + }, + } satisfies ModalManagerInterface; +}; + +export const Component: FC<{ + closeModal: (id: string) => void; + zIndex: number; + isLast: boolean; + modal: { id: string } & OpenModalInterface; +}> = memo(({ isLast, modal, closeModal, zIndex }) => { + const decision = useDecisionModal(); + const closeModalFunction = useCallback(async () => { + if (modal.askClose) { + const open = await decision.open(); + if (!open) { + return; + } + } + modal?.onClose?.(); + closeModal(modal.id); + }, [modal.id, closeModal]); + + const RenderComponent = useMemo(() => { + return typeof modal.children === 'function' + ? modal.children(closeModalFunction) + : modal.children; + }, [modal, closeModalFunction]); + + useHotkeys( + 'Escape', + () => { + if (isLast) { + closeModalFunction(); + } + }, + [isLast, closeModalFunction] + ); + + if (modal.removeLayout) { + return ( +
+
+
+
+ {typeof modal.children === 'function' + ? modal.children(closeModalFunction) + : modal.children} +
+
+
+
+ ); + } + + return ( + +
+
+
+
e.stopPropagation()} + > +
+
+ {modal.title} +
+ {typeof modal.withCloseButton === 'undefined' || + modal.withCloseButton ? ( +
+ +
+ ) : null} +
+
{RenderComponent}
+
+
+
+
+
+ ); +}); + +export const ModalManagerInner: FC = () => { + const { closeModal, modalManager } = useModalStore( + useShallow((state) => ({ + closeModal: state.closeById, + modalManager: state.modalManager, + })) + ); + + useEffect(() => { + if (modalManager.length > 0) { + document.querySelector('body')?.classList.add('overflow-hidden'); + Array.from(document.querySelectorAll('.blurMe') || []).map((p) => + p.classList.add('blur-xs', 'pointer-events-none') + ); + } else { + document.querySelector('body')?.classList.remove('overflow-hidden'); + Array.from(document.querySelectorAll('.blurMe') || []).map((p) => + p.classList.remove('blur-xs', 'pointer-events-none') + ); + } + }, [modalManager]); + + if (modalManager.length === 0) { + return null; + } + + return ( + <> + + {modalManager.map((modal, index) => ( + + ))} + + ); +}; +export const ModalManager: FC<{ children: ReactNode }> = ({ children }) => { + return ( +
+ + +
{children}
+
+ ); +}; + +const emitter = new EventEmitter(); +export const showModalEmitter = (params: ModalManagerInterface) => { + emitter.emit('show', params); +}; + +export const ModalManagerEmitter: FC = () => { + const { showModal } = useModalStore( + useShallow((state) => ({ + showModal: state.openModal, + })) + ); + + useEffect(() => { + emitter.on('show', (params: OpenModalInterface) => { + showModal(params); + }); + + return () => { + emitter.removeAllListeners('show'); + }; + }, []); + return null; +}; + +export const DecisionModal: FC<{ + description: string; + approveLabel: string; + cancelLabel: string; + resolution: (value: boolean) => void; +}> = ({ description, cancelLabel, approveLabel, resolution }) => { + const { closeCurrent } = useModals(); + return ( +
+
{description}
+
+ + +
+
+ ); +}; + +export const decisionModalEmitter = new EventEmitter(); + +export const areYouSure = ({ + title = 'Are you sure?', + description = 'Are you sure you want to close this modal?' as any, + approveLabel = 'Yes', + cancelLabel = 'No', +} = {}): Promise => { + return new Promise((newRes) => { + decisionModalEmitter.emit('open', { + title, + description, + approveLabel, + cancelLabel, + newRes, + }); + }); +}; + +export const DecisionEverywhere: FC = () => { + const decision = useDecisionModal(); + useEffect(() => { + decisionModalEmitter.on('open', decision.open); + }, []); + return null; +}; + +export const useDecisionModal = () => { + const modals = useModals(); + const open = useCallback( + ({ + title = 'Are you sure?', + description = 'Are you sure you want to close this modal?' as any, + approveLabel = 'Yes', + cancelLabel = 'No', + newRes = undefined as any, + } = {}) => { + return new Promise((res) => { + modals.openModal({ + title, + askClose: false, + onClose: () => res(false), + children: ( + (newRes ? newRes(value) : res(value))} + description={description} + approveLabel={approveLabel} + cancelLabel={cancelLabel} + /> + ), + }); + }); + }, + [modals] + ); + + return { open }; +}; diff --git a/apps/frontend/src/components/layout/pre-condition.component.tsx b/apps/frontend/src/components/layout/pre-condition.component.tsx index 081fb92f..a42c5442 100644 --- a/apps/frontend/src/components/layout/pre-condition.component.tsx +++ b/apps/frontend/src/components/layout/pre-condition.component.tsx @@ -1,19 +1,26 @@ import React, { FC, useEffect } from 'react'; import { useSearchParams } from 'next/navigation'; import { ModalWrapperComponent } from '@gitroom/frontend/components/new-launch/modal.wrapper.component'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Button } from '@gitroom/react/form/button'; export const PreConditionComponentModal: FC = () => { return (
- This social channel was connected previously to another Postiz account.{'\n'} - To continue, please fast-track your trial for an immediate charge.{'\n'}{'\n'} - ** Please be advised that the account will not eligible for a refund, and the charge is final. + This social channel was connected previously to another Postiz account. + {'\n'} + To continue, please fast-track your trial for an immediate charge.{'\n'} + {'\n'} + ** Please be advised that the account will not eligible for a refund, + and the charge is final.
- +
@@ -25,17 +32,13 @@ export const PreConditionComponent: FC = () => { useEffect(() => { if (query.get('precondition')) { modal.openModal({ - title: '', + title: 'Suspicious activity detected', withCloseButton: false, classNames: { modal: 'text-textColor', }, size: 'auto', - children: ( - - - - ), + children: , }); } }, []); diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx index 514bcc37..f0529caf 100644 --- a/apps/frontend/src/components/layout/settings.component.tsx +++ b/apps/frontend/src/components/layout/settings.component.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import React, { FC, Ref, diff --git a/apps/frontend/src/components/layout/top.menu.tsx b/apps/frontend/src/components/layout/top.menu.tsx index 66c78d98..7f7a6a5a 100644 --- a/apps/frontend/src/components/layout/top.menu.tsx +++ b/apps/frontend/src/components/layout/top.menu.tsx @@ -128,39 +128,39 @@ export const useMenuItem = () => { ] satisfies MenuItemInterface[] as MenuItemInterface[]; const secondMenu = [ - { - name: 'GrowChief', - icon: ( - - - - - - ), - path: 'https://growchief.com', - role: ['ADMIN', 'SUPERADMIN', 'USER'], - requireBilling: true, - }, + // { + // name: 'GrowChief', + // icon: ( + // + // + // + // + // + // ), + // path: 'https://growchief.com', + // role: ['ADMIN', 'SUPERADMIN', 'USER'], + // requireBilling: true, + // }, { name: t('affiliate', 'Affiliate'), icon: ( @@ -286,7 +286,7 @@ export const TopMenu: FC = () => { const { isGeneral, billingEnabled } = useVariables(); return ( <> -
+
{ // @ts-ignore user?.orgId && @@ -318,7 +318,7 @@ export const TopMenu: FC = () => { )) }
-
+
{secondMenu .filter((f) => { if (f.hide) { diff --git a/apps/frontend/src/components/marketplace/buyer.tsx b/apps/frontend/src/components/marketplace/buyer.tsx index 24742577..064c2faf 100644 --- a/apps/frontend/src/components/marketplace/buyer.tsx +++ b/apps/frontend/src/components/marketplace/buyer.tsx @@ -20,7 +20,7 @@ import { import { capitalize, chunk, fill } from 'lodash'; import useSWR from 'swr'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Textarea } from '@gitroom/react/form/textarea'; import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'; diff --git a/apps/frontend/src/components/marketplace/order.top.actions.tsx b/apps/frontend/src/components/marketplace/order.top.actions.tsx index d68bf37a..aaa5f072 100644 --- a/apps/frontend/src/components/marketplace/order.top.actions.tsx +++ b/apps/frontend/src/components/marketplace/order.top.actions.tsx @@ -1,7 +1,7 @@ import React, { FC, useCallback, useContext, useMemo, useState } from 'react'; import { MarketplaceProvider } from '@gitroom/frontend/components/marketplace/marketplace.provider'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Input } from '@gitroom/react/form/input'; import { CustomSelect } from '@gitroom/react/form/custom.select'; diff --git a/apps/frontend/src/components/marketplace/seller.tsx b/apps/frontend/src/components/marketplace/seller.tsx index 44f2831a..7370c257 100644 --- a/apps/frontend/src/components/marketplace/seller.tsx +++ b/apps/frontend/src/components/marketplace/seller.tsx @@ -10,7 +10,7 @@ import useSWR from 'swr'; import { Input } from '@gitroom/react/form/input'; import { useDebouncedCallback } from 'use-debounce'; import { OrderList } from '@gitroom/frontend/components/marketplace/order.list'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Select } from '@gitroom/react/form/select'; import { countries } from '@gitroom/nestjs-libraries/services/stripe.country.list'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/marketplace/special.message.tsx b/apps/frontend/src/components/marketplace/special.message.tsx index 8ac5fccc..f48d8d62 100644 --- a/apps/frontend/src/components/marketplace/special.message.tsx +++ b/apps/frontend/src/components/marketplace/special.message.tsx @@ -9,7 +9,7 @@ import useSWR from 'swr'; import { capitalize } from 'lodash'; import removeMd from 'remove-markdown'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Post as PrismaPost } from '@prisma/client'; import dynamic from 'next/dynamic'; import { IntegrationContext } from '@gitroom/frontend/components/launches/helpers/use.integration'; diff --git a/apps/frontend/src/components/media/media.component.tsx b/apps/frontend/src/components/media/media.component.tsx index 4d3e6ed3..2cccd77b 100644 --- a/apps/frontend/src/components/media/media.component.tsx +++ b/apps/frontend/src/components/media/media.component.tsx @@ -30,9 +30,13 @@ import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { ThirdPartyMedia } from '@gitroom/frontend/components/third-parties/third-party.media'; import { ReactSortable } from 'react-sortablejs'; -import { useMediaSettings } from '@gitroom/frontend/components/launches/helpers/media.settings.component'; +import { + MediaComponentInner, + useMediaSettings, +} from '@gitroom/frontend/components/launches/helpers/media.settings.component'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; import { AiVideo } from '@gitroom/frontend/components/launches/ai.video'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; const Polonto = dynamic( () => import('@gitroom/frontend/components/launches/polonto') ); @@ -246,7 +250,7 @@ export const MediaBox: FC<{ const dragAndDrop = useCallback( async (event: ClipboardEvent | File[]) => { if (!ref?.current?.setOptions) { - return ; + return; } // @ts-ignore @@ -564,12 +568,12 @@ export const MultiMediaComponent: FC<{ dummy, } = props; const user = useUser(); + const modals = useModals(); useEffect(() => { if (value) { setCurrentMedia(value); } }, [value]); - const [modal, setShowModal] = useState(false); const [mediaModal, setMediaModal] = useState(false); const [currentMedia, setCurrentMedia] = useState(value); const mediaDirectory = useMediaDirectory(); @@ -598,17 +602,14 @@ export const MultiMediaComponent: FC<{ [currentMedia] ); const showModal = useCallback(() => { - if (!modal) { - onOpen?.(); - } else { - onClose?.(); - } - setShowModal(!modal); - }, [modal, onOpen, onClose]); - const closeDesignModal = useCallback(() => { - onClose?.(); - setMediaModal(false); - }, [modal]); + modals.openModal({ + askClose: false, + children: (close) => ( + + ), + }); + }, [changeMedia]); + const clearMedia = useCallback( (topIndex: number) => () => { const newMedia = currentMedia?.filter((f, index) => index !== topIndex); @@ -622,10 +623,19 @@ export const MultiMediaComponent: FC<{ }, [currentMedia] ); + const designMedia = useCallback(() => { - onOpen?.(); - setMediaModal(true); - }, []); + if (!!user?.tier?.ai && !dummy) { + modals.openModal({ + askClose: false, + title: 'Design Media', + size: '80%', + children: (close) => ( + + ), + }); + } + }, [changeMedia]); const mediaSettings = useMediaSettings(); @@ -634,11 +644,6 @@ export const MultiMediaComponent: FC<{ return ( <>
- {modal && } - {mediaModal && !!user?.tier?.ai && !dummy && ( - - )} -
); }; diff --git a/apps/frontend/src/components/new-launch/modal.wrapper.component.tsx b/apps/frontend/src/components/new-launch/modal.wrapper.component.tsx index 4aec3391..e7de6d09 100644 --- a/apps/frontend/src/components/new-launch/modal.wrapper.component.tsx +++ b/apps/frontend/src/components/new-launch/modal.wrapper.component.tsx @@ -1,5 +1,5 @@ import { FC, ReactNode, useEffect, useRef } from 'react'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/new-layout/layout.component.tsx b/apps/frontend/src/components/new-layout/layout.component.tsx index abcfe4c5..c27c7a94 100644 --- a/apps/frontend/src/components/new-layout/layout.component.tsx +++ b/apps/frontend/src/components/new-layout/layout.component.tsx @@ -69,6 +69,7 @@ export const LayoutComponent = ({ children }: { children: ReactNode }) => { {user.tier === 'FREE' && searchParams.get('check') && ( @@ -103,7 +104,7 @@ export const LayoutComponent = ({ children }: { children: ReactNode }) => {
-
+
diff --git a/apps/frontend/src/components/onboarding/onboarding.tsx b/apps/frontend/src/components/onboarding/onboarding.tsx index 7e5f776b..30a0d9cc 100644 --- a/apps/frontend/src/components/onboarding/onboarding.tsx +++ b/apps/frontend/src/components/onboarding/onboarding.tsx @@ -2,7 +2,7 @@ import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { Button } from '@gitroom/react/form/button'; import { ConnectChannels } from '@gitroom/frontend/components/onboarding/connect.channels'; import { useVariables } from '@gitroom/react/helpers/variable.context'; @@ -46,15 +46,11 @@ export const Onboarding: FC = () => { } modalOpen.current = true; modal.openModal({ - title: '', + title: t('onboarding', 'Onboarding'), withCloseButton: false, closeOnEscape: false, size: '900px', - children: ( - <ModalWrapperComponent title={t('onboarding', 'Onboarding')}> - <Welcome /> - </ModalWrapperComponent> - ), + children: <Welcome />, }); }, [query]); return null; diff --git a/apps/frontend/src/components/plugs/plug.tsx b/apps/frontend/src/components/plugs/plug.tsx index eb5f8e06..de6978ec 100644 --- a/apps/frontend/src/components/plugs/plug.tsx +++ b/apps/frontend/src/components/plugs/plug.tsx @@ -9,7 +9,7 @@ import { Button } from '@gitroom/react/form/button'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR, { mutate } from 'swr'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { FormProvider, @@ -243,18 +243,17 @@ export const Plug = () => { mutate(); }, size: '500px', + title: `Auto Plug: ${p.title}`, children: ( - <ModalWrapperComponent title={`Auto Plug: ${p.title}`}> - <PlugPop - plug={p} - data={data} - settings={{ - identifier: plug.identifier, - providerId: plug.providerId, - name: plug.name, - }} - /> - </ModalWrapperComponent> + <PlugPop + plug={p} + data={data} + settings={{ + identifier: plug.identifier, + providerId: plug.providerId, + name: plug.name, + }} + /> ), }); }, diff --git a/apps/frontend/src/components/preview/preview.wrapper.tsx b/apps/frontend/src/components/preview/preview.wrapper.tsx index 9022b106..ac45172a 100644 --- a/apps/frontend/src/components/preview/preview.wrapper.tsx +++ b/apps/frontend/src/components/preview/preview.wrapper.tsx @@ -26,6 +26,7 @@ export const PreviewWrapper = ({ children }: { children: ReactNode }) => { <CopilotKit credentials="include" runtimeUrl={backendUrl + '/copilot/chat'} + showDevConsole={false} > <MantineWrapper> <Toaster /> diff --git a/apps/frontend/src/components/sets/sets.tsx b/apps/frontend/src/components/sets/sets.tsx index ab01add9..0f8e65a0 100644 --- a/apps/frontend/src/components/sets/sets.tsx +++ b/apps/frontend/src/components/sets/sets.tsx @@ -6,15 +6,14 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR from 'swr'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { Button } from '@gitroom/react/form/button'; -import { useModals } from '@mantine/modals'; import { Input } from '@gitroom/react/form/input'; import { useToaster } from '@gitroom/react/toaster/toaster'; import clsx from 'clsx'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import dayjs from 'dayjs'; import { AddEditModal } from '@gitroom/frontend/components/new-launch/add.edit.modal'; import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; const SaveSetModal: FC<{ postData: any; @@ -97,9 +96,8 @@ export const Sets: FC = () => { closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, - classNames: { - modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor', - }, + removeLayout: true, + askClose: true, children: ( <AddEditModal allIntegrations={integrations.map((p: any) => ({ @@ -109,10 +107,6 @@ export const Sets: FC = () => { addEditSets={(data) => { modal.openModal({ title: 'Save as Set', - classNames: { - modal: 'bg-sixth text-textColor', - title: 'text-textColor', - }, children: ( <SaveSetModal initialValue={params?.name || ''} @@ -137,7 +131,6 @@ export const Sets: FC = () => { onCancel={() => modal.closeAll()} /> ), - size: 'md', }); }} reopenModal={() => {}} @@ -146,7 +139,6 @@ export const Sets: FC = () => { date={newDayjs()} /> ), - size: '80%', title: ``, }); }, diff --git a/apps/frontend/src/components/settings/signatures.component.tsx b/apps/frontend/src/components/settings/signatures.component.tsx index 3bfa870d..19ff9aad 100644 --- a/apps/frontend/src/components/settings/signatures.component.tsx +++ b/apps/frontend/src/components/settings/signatures.component.tsx @@ -3,7 +3,7 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR from 'swr'; import { Button } from '@gitroom/react/form/button'; import clsx from 'clsx'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { array, boolean, object, string } from 'yup'; import { FormProvider, useForm } from 'react-hook-form'; @@ -27,11 +27,8 @@ export const SignaturesComponent: FC<{ const addSignature = useCallback( (data?: any) => () => { modal.openModal({ - title: '', - withCloseButton: false, - classNames: { - modal: 'bg-transparent text-textColor', - }, + title: data ? 'Edit Signature' : 'Add Signature', + withCloseButton: true, children: <AddOrRemoveSignature data={data} reload={mutate} />, }); }, @@ -170,7 +167,7 @@ const AddOrRemoveSignature: FC<{ : 'Signature added successfully', 'success' ); - modal.closeModal(modal.modals[modal.modals.length - 1].id); + modal.closeCurrent(); reload(); }, [data, modal] @@ -181,14 +178,11 @@ const AddOrRemoveSignature: FC<{ return ( <FormProvider {...form}> <form onSubmit={form.handleSubmit(callBack)}> - <div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0 w-[500px]"> - <TopTitle title={data ? 'Edit Signature' : 'Add Signature'} /> + <div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] pt-0"> <button className="outline-none absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa" type="button" - onClick={() => - modal.closeModal(modal.modals[modal.modals.length - 1].id) - } + onClick={() => modal.closeCurrent()} > <svg viewBox="0 0 15 15" diff --git a/apps/frontend/src/components/settings/teams.component.tsx b/apps/frontend/src/components/settings/teams.component.tsx index 75a0b91d..394ed17a 100644 --- a/apps/frontend/src/components/settings/teams.component.tsx +++ b/apps/frontend/src/components/settings/teams.component.tsx @@ -4,7 +4,7 @@ import useSWR from 'swr'; import React, { useCallback, useMemo } from 'react'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { capitalize } from 'lodash'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Input } from '@gitroom/react/form/input'; import { useForm, FormProvider, useWatch } from 'react-hook-form'; @@ -65,38 +65,13 @@ export const AddMember = () => { }, [] ); - const closeModal = useCallback(() => { - return modals.closeAll(); - }, []); const t = useT(); return ( <FormProvider {...form}> <form onSubmit={form.handleSubmit(submit)}> - <div className="relative flex gap-[10px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0"> - <TopTitle title="Add Member" /> - <button - onClick={closeModal} - className="outline-none absolute end-[20px] top-[20px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa" - type="button" - > - <svg - viewBox="0 0 15 15" - fill="none" - xmlns="http://www.w3.org/2000/svg" - width="16" - height="16" - > - <path - d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" - fill="currentColor" - fillRule="evenodd" - clipRule="evenodd" - ></path> - </svg> - </button> - + <div className="relative flex gap-[10px] flex-col flex-1 p-[16px] pt-0"> {sendEmail && ( <Input label="Email" @@ -153,7 +128,8 @@ export const TeamsComponent = () => { classNames: { modal: 'bg-transparent text-textColor', }, - withCloseButton: false, + title: 'Add Team Member', + withCloseButton: true, children: <AddMember />, }); }, []); diff --git a/apps/frontend/src/components/signature.tsx b/apps/frontend/src/components/signature.tsx index 1148ec1f..d1ee4b0f 100644 --- a/apps/frontend/src/components/signature.tsx +++ b/apps/frontend/src/components/signature.tsx @@ -1,27 +1,26 @@ -import { FC, useCallback, useState } from 'react'; -import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; +import { FC, useCallback } from 'react'; import { SignaturesComponent } from '@gitroom/frontend/components/settings/signatures.component'; -import { Transforms } from 'slate'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; export const SignatureBox: FC<{ editor: any; }> = ({ editor }) => { - const [showModal, setShowModal] = useState<any>(false); - const addSignature = useCallback(() => { - setShowModal(true); - }, [showModal]); + const modals = useModals(); const appendValue = (val: string) => { - editor?.commands?.insertContent("\n\n" + val); + editor?.commands?.insertContent('\n\n' + val); editor?.commands?.focus(); - setShowModal(false); }; + + const addSignature = useCallback(() => { + modals.openModal({ + title: 'Add Signature', + children: (close) => ( + <SignatureModal appendSignature={appendValue} close={close} /> + ), + }); + }, [appendValue]); + return ( <> - {showModal && ( - <SignatureModal - appendSignature={appendValue} - close={() => setShowModal(false)} - /> - )} <div onClick={addSignature} className="select-none cursor-pointer w-[40px] p-[5px] text-center" @@ -45,32 +44,10 @@ export const SignatureModal: FC<{ close: () => void; appendSignature: (sign: string) => void; }> = (props) => { - const { close, appendSignature } = props; + const { appendSignature } = props; return ( <div className="bg-black/40 fixed start-0 top-0 w-full h-full z-[500]"> - <div className="relative w-[900px] mx-auto flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0"> - <TopTitle title={`Add signature`} /> - <button - className="outline-none absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa" - type="button" - > - <svg - viewBox="0 0 15 15" - fill="none" - xmlns="http://www.w3.org/2000/svg" - width="16" - height="16" - onClick={close} - > - <path - d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" - fill="currentColor" - fillRule="evenodd" - clipRule="evenodd" - ></path> - </svg> - </button> - + <div className="relative w-[900px] mx-auto flex gap-[20px] flex-col flex-1 rounded-[4px] pt-0"> <SignaturesComponent appendSignature={appendSignature} /> </div> </div> diff --git a/apps/frontend/src/components/third-parties/third-party.list.component.tsx b/apps/frontend/src/components/third-parties/third-party.list.component.tsx index 6e6d8ed2..9dcaea7b 100644 --- a/apps/frontend/src/components/third-parties/third-party.list.component.tsx +++ b/apps/frontend/src/components/third-parties/third-party.list.component.tsx @@ -5,7 +5,7 @@ import useSWR from 'swr'; import React, { FC, useCallback, useState } from 'react'; import { Button } from '@gitroom/react/form/button'; import { useRouter } from 'next/navigation'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { FieldValues, FormProvider, useForm } from 'react-hook-form'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { Input } from '@gitroom/react/form/input'; @@ -115,12 +115,10 @@ export const ThirdPartyListComponent: FC<{ reload: () => void }> = (props) => { const addApiKey = useCallback( (title: string, identifier: string) => () => { modals.openModal({ - title: '', + title: `Add API key for ${title}`, withCloseButton: false, children: ( - <ModalWrapperComponent title={`Add API key for ${title}`}> - <ApiModal identifier={identifier} title={title} update={reload} /> - </ModalWrapperComponent> + <ApiModal identifier={identifier} title={title} update={reload} /> ), }); }, diff --git a/apps/frontend/src/components/third-parties/third-party.media.tsx b/apps/frontend/src/components/third-parties/third-party.media.tsx index e4a7d639..2729607c 100644 --- a/apps/frontend/src/components/third-parties/third-party.media.tsx +++ b/apps/frontend/src/components/third-parties/third-party.media.tsx @@ -18,6 +18,7 @@ import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.titl import './providers/heygen.provider'; import { thirdPartyList } from '@gitroom/frontend/components/third-parties/third-party.wrapper'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; const ThirdPartyContext = createContext({ id: '', @@ -92,93 +93,53 @@ export const ThirdPartyPopup: FC<{ }, []); return ( - <div - className="removeEditor fixed start-0 top-0 bg-primary/80 z-[300] w-full min-h-full animate-fade bg-black/30 rounded-[24px]" - onClick={closeModal} - > - <div className="relative"> - <div className="absolute -top-[50px] left-0" ref={refNew} /> - </div> - <div - className="max-w-[1000px] w-full h-full bg-sixth border-tableBorder border-2 rounded-xl relative mx-auto" - onClick={(e) => e.stopPropagation()} - > - <div className="pb-[20px] px-[20px] w-full h-full"> - <div className="flex flex-col"> - <div className="flex-1"> - <TopTitle title="Integrations" /> - </div> - <button - onClick={closeModal} - className="outline-none z-[300] absolute end-[20px] top-[20px] mantine-UnstyledButton-root mantine-ActionIcon-root bg-primary hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa" - type="button" + <div className={clsx('flex flex-wrap flex-col gap-[10px] pt-[20px]')}> + {!thirdParty && ( + <div className="grid grid-cols-4 gap-[10px] justify-items-center justify-center"> + {thirdParties.map((p: any) => ( + <div + onClick={() => { + setThirdParty(p); + }} + key={p.identifier} + className="w-full h-full p-[20px] min-h-[100px] text-[14px] bg-third hover:bg-input transition-all text-textColor relative flex flex-col gap-[15px] cursor-pointer" > - <svg - viewBox="0 0 15 15" - fill="none" - xmlns="http://www.w3.org/2000/svg" - width="16" - height="16" - > - <path - d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" - fill="currentColor" - fillRule="evenodd" - clipRule="evenodd" - ></path> - </svg> - </button> - </div> - <div className={clsx('flex flex-wrap flex-col gap-[10px] pt-[20px]')}> - {!thirdParty && ( - <div className="grid grid-cols-4 gap-[10px] justify-items-center justify-center"> - {thirdParties.map((p: any) => ( - <div - onClick={() => { - setThirdParty(p); - }} - key={p.identifier} - className="w-full h-full p-[20px] min-h-[100px] text-[14px] bg-third hover:bg-input transition-all text-textColor relative flex flex-col gap-[15px] cursor-pointer" - > - <div> - <img - className="w-[32px] h-[32px]" - src={`/icons/third-party/${p.identifier}.png`} - /> - </div> - <div className="whitespace-pre-wrap text-left text-lg"> - {p.title}: {p.name} - </div> - <div className="whitespace-pre-wrap text-left"> - {p.description} - </div> - <div className="w-full flex"> - <Button className="w-full">Use</Button> - </div> - </div> - ))} + <div> + <img + className="w-[32px] h-[32px]" + src={`/icons/third-party/${p.identifier}.png`} + /> </div> - )} - {thirdParty && ( - <> - <div> - <div - className="cursor-pointer float-left" - onClick={() => setThirdParty(null)} - > - {'<'} Back - </div> - </div> - <ThirdPartyContext.Provider - value={{ ...thirdParty, data: allData, close, onChange }} - > - <Component /> - </ThirdPartyContext.Provider> - </> - )} - </div> + <div className="whitespace-pre-wrap text-left text-lg"> + {p.title}: {p.name} + </div> + <div className="whitespace-pre-wrap text-left"> + {p.description} + </div> + <div className="w-full flex"> + <Button className="w-full">Use</Button> + </div> + </div> + ))} </div> - </div> + )} + {thirdParty && ( + <> + <div> + <div + className="cursor-pointer float-left" + onClick={() => setThirdParty(null)} + > + {'<'} Back + </div> + </div> + <ThirdPartyContext.Provider + value={{ ...thirdParty, data: allData, close, onChange }} + > + <Component /> + </ThirdPartyContext.Provider> + </> + )} </div> ); }; @@ -197,7 +158,7 @@ export const ThirdPartyMedia: FC<{ const { allData, onChange } = props; const t = useT(); const fetch = useFetch(); - const [popup, setPopup] = useState(false); + const modals = useModals(); const thirdParties = useCallback(async () => { return (await (await fetch('/third-party')).json()).filter( @@ -220,20 +181,25 @@ export const ThirdPartyMedia: FC<{ return ( <> - {popup && ( - <ThirdPartyPopup - thirdParties={data} - closeModal={() => setPopup(false)} - allData={allData} - onChange={onChange} - /> - )} <div className="relative group"> <Button className={clsx( 'relative ms-[10px] !px-[10px] rounded-[4px] gap-[8px] !text-primary justify-center items-center flex border border-dashed border-newBgLineColor bg-newColColor' )} - onClick={() => setPopup(true)} + onClick={() => { + modals.openModal({ + title: t('integrations', 'Integrations'), + size: '80%', + children: (close) => ( + <ThirdPartyPopup + thirdParties={data} + closeModal={close} + allData={allData} + onChange={onChange} + /> + ), + }); + }} > <div className={clsx('flex gap-[5px] items-center')}> <div> diff --git a/apps/frontend/src/components/webhooks/webhooks.tsx b/apps/frontend/src/components/webhooks/webhooks.tsx index 6f5d87a3..89245a23 100644 --- a/apps/frontend/src/components/webhooks/webhooks.tsx +++ b/apps/frontend/src/components/webhooks/webhooks.tsx @@ -3,7 +3,7 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR from 'swr'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { Button } from '@gitroom/react/form/button'; -import { useModals } from '@mantine/modals'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Input } from '@gitroom/react/form/input'; import { FormProvider, useForm } from 'react-hook-form'; @@ -27,11 +27,8 @@ export const Webhooks: FC = () => { const addWebhook = useCallback( (data?: any) => () => { modal.openModal({ - title: '', - withCloseButton: false, - classNames: { - modal: 'bg-transparent text-textColor', - }, + title: data ? 'Update webhook' : 'Add webhook', + withCloseButton: true, children: <AddOrEditWebhook data={data} reload={mutate} />, }); }, @@ -246,29 +243,7 @@ export const AddOrEditWebhook: FC<{ return ( <FormProvider {...form}> <form onSubmit={form.handleSubmit(callBack)}> - <div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0 w-[500px]"> - <TopTitle title={data ? 'Edit webhook' : 'Add webhook'} /> - <button - className="outline-none absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa" - type="button" - onClick={modal.closeAll} - > - <svg - viewBox="0 0 15 15" - fill="none" - xmlns="http://www.w3.org/2000/svg" - width="16" - height="16" - > - <path - d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" - fill="currentColor" - fillRule="evenodd" - clipRule="evenodd" - ></path> - </svg> - </button> - + <div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] pt-0"> <div> <Input label="Name" diff --git a/apps/frontend/tailwind.config.js b/apps/frontend/tailwind.config.js index 71fa7e9b..19527704 100644 --- a/apps/frontend/tailwind.config.js +++ b/apps/frontend/tailwind.config.js @@ -73,8 +73,6 @@ module.exports = { customColor55: 'var(--color-custom55)', modalCustom: 'var(--color-modalCustom)', - - newBgColor: 'var(--new-bgColor)', newBgColorInner: 'var(--new-bgColorInner)', newBgLineColor: 'var(--new-bgLineColor)', @@ -96,6 +94,7 @@ module.exports = { menuDots: 'var(--new-menu-dots)', menuDotsHover: 'var(--new-menu-hover)', bigStrip: 'var(--new-big-strips)', + popup: 'var(--popup-color)', }, gridTemplateColumns: { 13: 'repeat(13, minmax(0, 1fr));', @@ -110,6 +109,7 @@ module.exports = { animation: { fade: 'fadeOut 0.5s ease-in-out', normalFadeIn: 'normalFadeIn 0.5s ease-in-out', + fadeIn: 'normalFadeIn 0.2s ease-in-out forwards', normalFadeOut: 'normalFadeOut 0.5s linear 5s forwards', overflow: 'overFlow 0.5s ease-in-out forwards', overflowReverse: 'overFlowReverse 0.5s ease-in-out forwards', @@ -121,7 +121,7 @@ module.exports = { yellow: '0 0 60px 20px #6b6237', yellowToast: '0px 0px 50px rgba(252, 186, 3, 0.3)', greenToast: '0px 0px 50px rgba(60, 124, 90, 0.3)', - menu: 'var(--menu-shadow)' + menu: 'var(--menu-shadow)', }, // that is actual animation keyframes: (theme) => ({ diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/reddit.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/reddit.dto.ts index 8785ddbe..49c7462f 100644 --- a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/reddit.dto.ts +++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/reddit.dto.ts @@ -55,6 +55,7 @@ export class RedditSettingsDtoInner { @ValidateIf((e) => e.is_flair_required) @IsDefined() @ValidateNested() + @Type(() => RedditFlairDto) flair: RedditFlairDto; } diff --git a/libraries/react-shared-libraries/src/form/checkbox.tsx b/libraries/react-shared-libraries/src/form/checkbox.tsx index dc53837e..0ac34c2c 100644 --- a/libraries/react-shared-libraries/src/form/checkbox.tsx +++ b/libraries/react-shared-libraries/src/form/checkbox.tsx @@ -50,7 +50,7 @@ export const Checkbox = forwardRef< {...disableForm ? {} : form.register(props.name!)} onClick={changeStatus} className={clsx( - 'cursor-pointer rounded-[4px] select-none w-[24px] h-[24px] justify-center items-center flex', + 'cursor-pointer rounded-[4px] select-none w-[24px] h-[24px] justify-center items-center flex text-white', variant === 'default' || !variant ? 'bg-forth' : 'border-customColor1 border-2 bg-customColor2', diff --git a/libraries/react-shared-libraries/src/helpers/delete.dialog.tsx b/libraries/react-shared-libraries/src/helpers/delete.dialog.tsx index 47146c23..81071b7c 100644 --- a/libraries/react-shared-libraries/src/helpers/delete.dialog.tsx +++ b/libraries/react-shared-libraries/src/helpers/delete.dialog.tsx @@ -1,5 +1,5 @@ -import Swal from 'sweetalert2'; import i18next from '@gitroom/react/translation/i18next'; +import { areYouSure } from '@gitroom/frontend/components/layout/new-modal'; export const deleteDialog = async ( message: string, @@ -7,14 +7,11 @@ export const deleteDialog = async ( title?: string, cancelButton?: string ) => { - const fire = await Swal.fire({ + return areYouSure({ title: title || i18next.t('are_you_sure', 'Are you sure?'), - text: message, - icon: 'warning', - showCancelButton: true, - confirmButtonText: + description: message, + approveLabel: confirmButton || i18next.t('yes_delete_it', 'Yes, delete it!'), - cancelButtonText: cancelButton || i18next.t('no_cancel', 'No, cancel!'), + cancelLabel: cancelButton || i18next.t('no_cancel', 'No, cancel!'), }); - return fire.isConfirmed; }; diff --git a/libraries/react-shared-libraries/src/helpers/mantine.wrapper.tsx b/libraries/react-shared-libraries/src/helpers/mantine.wrapper.tsx index ffdaa18a..3776f4e2 100644 --- a/libraries/react-shared-libraries/src/helpers/mantine.wrapper.tsx +++ b/libraries/react-shared-libraries/src/helpers/mantine.wrapper.tsx @@ -1,26 +1,15 @@ 'use client'; import { ReactNode } from 'react'; -import { MantineProvider } from '@mantine/core'; -import { ModalsProvider } from '@mantine/modals'; -import i18next from '@gitroom/react/translation/i18next'; +import { + DecisionEverywhere, + ModalManager, +} from '@gitroom/frontend/components/layout/new-modal'; export const MantineWrapper = (props: { children: ReactNode }) => { - const dir = i18next.dir(); - return ( - // @ts-ignore - <MantineProvider> - <ModalsProvider - modalProps={{ - dir, - classNames: { - modal: 'bg-primary text-white', - close: 'bg-black hover:bg-black cursor-pointer', - }, - }} - > - {props.children} - </ModalsProvider> - </MantineProvider> + <ModalManager> + <DecisionEverywhere /> + {props.children} + </ModalManager> ); }; diff --git a/package.json b/package.json index 5bed657f..3cb32400 100644 --- a/package.json +++ b/package.json @@ -186,6 +186,7 @@ "react-dom": "18.3.1", "react-dropzone": "^14.3.5", "react-hook-form": "^7.58.1", + "react-hotkeys-hook": "^5.1.0", "react-i18next": "^15.5.2", "react-loading": "^2.0.3", "react-sortablejs": "^6.1.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 808a6062..e7f0632e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,7 +57,7 @@ importers: '@mantine/hooks': specifier: ^5.10.5 version: 5.10.5(react@18.3.1) - '@mantine/modals': + '@gitroom/frontend/components/layout/new-modal': specifier: ^5.10.5 version: 5.10.5(@mantine/core@5.10.5(@emotion/react@11.14.0(@types/react@18.3.1)(react@18.3.1))(@mantine/hooks@5.10.5(react@18.3.1))(@types/react@18.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@5.10.5(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@modelcontextprotocol/sdk': @@ -438,6 +438,9 @@ importers: react-hook-form: specifier: ^7.58.1 version: 7.62.0(react@18.3.1) + react-hotkeys-hook: + specifier: ^5.1.0 + version: 5.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-i18next: specifier: ^15.5.2 version: 15.7.3(i18next@25.5.2(typescript@5.5.4))(react-dom@18.3.1(react@18.3.1))(react-native@0.81.4(@babel/core@7.28.4)(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(typescript@5.5.4) @@ -12884,6 +12887,12 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 + react-hotkeys-hook@5.1.0: + resolution: {integrity: sha512-GCNGXjBzV9buOS3REoQFmSmE4WTvBhYQ0YrAeeMZI83bhXg3dRWsLHXDutcVDdEjwJqJCxk5iewWYX5LtFUd7g==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + react-i18next@15.7.3: resolution: {integrity: sha512-AANws4tOE+QSq/IeMF/ncoHlMNZaVLxpa5uUGW1wjike68elVYr0018L9xYoqBr1OFO7G7boDPrbn0HpMCJxTw==} peerDependencies: @@ -31585,6 +31594,11 @@ snapshots: dependencies: react: 18.3.1 + react-hotkeys-hook@5.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-i18next@15.7.3(i18next@25.5.2(typescript@5.5.4))(react-dom@18.3.1(react@18.3.1))(react-native@0.81.4(@babel/core@7.28.4)(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(typescript@5.5.4): dependencies: '@babel/runtime': 7.28.4