From 958b92c03871bcbf897f4ffc10b57bbee4927371 Mon Sep 17 00:00:00 2001 From: Amjad Marblism Date: Tue, 17 Feb 2026 19:01:06 +0000 Subject: [PATCH 1/4] chore: front end refactoring and some useless calls that will be functioning tomorrow --- app/designSystem/landing/ChatBarForm.tsx | 65 ++++ app/designSystem/landing/ChatHistory.tsx | 49 +++ app/designSystem/landing/LandingAvatar.tsx | 6 +- app/designSystem/landing/LandingCTA.tsx | 40 --- app/designSystem/landing/LandingContainer.tsx | 11 - app/designSystem/landing/LandingFAQ.tsx | 56 ---- app/designSystem/landing/LandingFeatures.tsx | 54 ---- app/designSystem/landing/LandingFooter.tsx | 49 --- app/designSystem/landing/LandingHero.tsx | 58 ---- .../landing/LandingHowItWorks.tsx | 47 --- .../LandingNavBar/landing.desktop.navbar.tsx | 49 --- .../LandingNavBar/landing.mobile.navbar.tsx | 88 ----- .../LandingNavBar/landing.navbar.items.tsx | 35 -- .../landing/LandingNavBar/landing.navbar.tsx | 26 -- .../landing/LandingPainPoints.tsx | 71 ----- app/designSystem/landing/LandingPricing.tsx | 105 ------ app/designSystem/landing/LandingRating.tsx | 65 ---- .../landing/LandingSocialProof.tsx | 34 -- .../landing/LandingSocialRating.tsx | 66 ---- .../landing/LandingTestimonials.tsx | 80 ----- app/designSystem/landing/images/linda.webp | Bin 0 -> 97410 bytes app/designSystem/landing/index.tsx | 12 +- app/routes/_auth.login_/route.tsx | 136 -------- app/routes/_auth.register_/route.tsx | 120 ------- .../_auth.reset-password.$token_/route.tsx | 126 -------- app/routes/_auth.reset-password_/route.tsx | 112 ------- app/routes/_index.tsx | 231 +------------- app/routes/_logged.home_/route.tsx | 92 ------ .../route.tsx | 123 ------- .../hooks/useDelete.tsx | 76 ----- .../hooks/useInvitation.tsx | 70 ---- .../hooks/useUpdate.tsx | 65 ---- .../route.tsx | 300 ------------------ .../route.tsx | 136 -------- .../route.tsx | 112 ------- app/routes/_logged.organizations/route.tsx | 22 -- app/routes/_logged.pricing_/route.tsx | 128 -------- app/routes/_logged.profile_/route.tsx | 120 ------- app/routes/hooks/handleChat.tsx | 0 39 files changed, 131 insertions(+), 2904 deletions(-) create mode 100644 app/designSystem/landing/ChatBarForm.tsx create mode 100644 app/designSystem/landing/ChatHistory.tsx delete mode 100644 app/designSystem/landing/LandingCTA.tsx delete mode 100644 app/designSystem/landing/LandingFAQ.tsx delete mode 100644 app/designSystem/landing/LandingFeatures.tsx delete mode 100644 app/designSystem/landing/LandingFooter.tsx delete mode 100644 app/designSystem/landing/LandingHero.tsx delete mode 100644 app/designSystem/landing/LandingHowItWorks.tsx delete mode 100644 app/designSystem/landing/LandingNavBar/landing.desktop.navbar.tsx delete mode 100644 app/designSystem/landing/LandingNavBar/landing.mobile.navbar.tsx delete mode 100644 app/designSystem/landing/LandingNavBar/landing.navbar.items.tsx delete mode 100644 app/designSystem/landing/LandingNavBar/landing.navbar.tsx delete mode 100644 app/designSystem/landing/LandingPainPoints.tsx delete mode 100644 app/designSystem/landing/LandingPricing.tsx delete mode 100644 app/designSystem/landing/LandingRating.tsx delete mode 100644 app/designSystem/landing/LandingSocialProof.tsx delete mode 100644 app/designSystem/landing/LandingSocialRating.tsx delete mode 100644 app/designSystem/landing/LandingTestimonials.tsx create mode 100644 app/designSystem/landing/images/linda.webp delete mode 100644 app/routes/_auth.login_/route.tsx delete mode 100644 app/routes/_auth.register_/route.tsx delete mode 100644 app/routes/_auth.reset-password.$token_/route.tsx delete mode 100644 app/routes/_auth.reset-password_/route.tsx delete mode 100644 app/routes/_logged.home_/route.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.home_/route.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.members_/hooks/useDelete.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.members_/hooks/useInvitation.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.members_/hooks/useUpdate.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.members_/route.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.pricing_/route.tsx delete mode 100644 app/routes/_logged.organizations.$organizationId.settings_/route.tsx delete mode 100644 app/routes/_logged.organizations/route.tsx delete mode 100644 app/routes/_logged.pricing_/route.tsx delete mode 100644 app/routes/_logged.profile_/route.tsx create mode 100644 app/routes/hooks/handleChat.tsx diff --git a/app/designSystem/landing/ChatBarForm.tsx b/app/designSystem/landing/ChatBarForm.tsx new file mode 100644 index 0000000..bfa1f2e --- /dev/null +++ b/app/designSystem/landing/ChatBarForm.tsx @@ -0,0 +1,65 @@ +import { InputHTMLAttributes, useState } from 'react' +import { Api } from '~/core/trpc' + +interface ChatBarFormProps extends InputHTMLAttributes {} + +/** + * Form component for the chat input bar, allowing users to type and submit messages. + */ +export const ChatBarForm = ({ + className, + ...remainingProps +}: ChatBarFormProps) => { + const login = Api.authentication.login.useMutation() + + const generateText = Api.ai.generateText.useMutation() + + const [message, setMessage] = useState('') + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault() + const user = await login.mutateAsync({ + email: 'test@test.com', + password: 'password', + }, { + onSuccess: (data) => { + console.log('Login successful:', data)} + }); + + console.log(JSON.stringify(user)) + console.log(message) + generateText.context = { + userId: '12345', + sessionId: 'abcde', + } + console.log(generateText.context) + await generateText.mutateAsync({ + prompt: message, + attachmentUrls: [], + provider: 'openai' + }).then((response) => { + console.log('AI response:', response) + }).catch((error) => { + console.error('Error generating text:', error) + }); + // Handle form submission logic here + setMessage(''); + } + + const handleChange = (event: React.ChangeEvent) => { + setMessage(event.target.value); + }; + + return ( +
+ + +
+ ) +} diff --git a/app/designSystem/landing/ChatHistory.tsx b/app/designSystem/landing/ChatHistory.tsx new file mode 100644 index 0000000..07d9650 --- /dev/null +++ b/app/designSystem/landing/ChatHistory.tsx @@ -0,0 +1,49 @@ +import { HTMLAttributes } from 'react' +import { DesignSystemUtility } from '../helpers/utility' +import LandingButton from './LandingButton' +import { LandingAvatar } from './LandingAvatar' + +interface Props extends HTMLAttributes { + messages: MessageHistory[] + title?: string + subtitle?: string + buttonText?: string + buttonLink?: string +} + +interface MessageHistory { + ai: boolean + text: string +} + +export const ChatHistory: React.FC = ({ + messages, + title, + subtitle, + buttonText, + buttonLink, + className, + ...props +}) => { + return ( +
+
+

{title}

+
+ {messages.map((message,index) => ( +
+ + + {message.text} +
+ ))} +
+
+
+ ) +} diff --git a/app/designSystem/landing/LandingAvatar.tsx b/app/designSystem/landing/LandingAvatar.tsx index 8040b13..67f43e6 100644 --- a/app/designSystem/landing/LandingAvatar.tsx +++ b/app/designSystem/landing/LandingAvatar.tsx @@ -11,9 +11,9 @@ interface LandingAvatarProps extends ImgHTMLAttributes { export const LandingAvatar = ({ className, src, - width = 128, - height = 128, - size = 'medium', + width = 256, + height = 256, + size = 'large', ...remainingProps }: LandingAvatarProps) => { return ( diff --git a/app/designSystem/landing/LandingCTA.tsx b/app/designSystem/landing/LandingCTA.tsx deleted file mode 100644 index 13415aa..0000000 --- a/app/designSystem/landing/LandingCTA.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' -import LandingButton from './LandingButton' - -interface Props extends HTMLAttributes { - title?: string - subtitle?: string - buttonText?: string - buttonLink?: string -} - -export const LandingCTA: React.FC = ({ - title, - subtitle, - buttonText, - buttonLink, - className, - ...props -}) => { - return ( -
-
-
-

- {title} -

-

{subtitle}

-
- - {buttonText} - -
-
-
-
- ) -} diff --git a/app/designSystem/landing/LandingContainer.tsx b/app/designSystem/landing/LandingContainer.tsx index d586ea6..8839797 100644 --- a/app/designSystem/landing/LandingContainer.tsx +++ b/app/designSystem/landing/LandingContainer.tsx @@ -1,28 +1,17 @@ import { HTMLAttributes } from 'react' -import { LandingFooter } from './LandingFooter' -import { LandingNavBar } from './LandingNavBar/landing.navbar' interface Props extends HTMLAttributes { - navItems: { - link: string - title: string - target?: '_blank' - }[] children: React.ReactNode } export const LandingContainer: React.FC = ({ - navItems, children, ...props }) => { return (
- {children} - -
) diff --git a/app/designSystem/landing/LandingFAQ.tsx b/app/designSystem/landing/LandingFAQ.tsx deleted file mode 100644 index d091296..0000000 --- a/app/designSystem/landing/LandingFAQ.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { ArrowRightOutlined } from '@ant-design/icons' -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' - -interface Props extends HTMLAttributes { - title: string - subtitle: string - questionAnswers: { question: string; answer: string }[] -} - -export const LandingFAQ: React.FC = ({ - title, - subtitle, - questionAnswers, - className, - ...props -}) => { - return ( -
-
-
-
-

- {title} -

-

- {subtitle} -

-
-
-
- {questionAnswers.map((item, index) => ( -
-
- - {item.question} - - - - -

- {item.answer} -

-
-
- ))} -
-
-
-
-
- ) -} diff --git a/app/designSystem/landing/LandingFeatures.tsx b/app/designSystem/landing/LandingFeatures.tsx deleted file mode 100644 index 8efc771..0000000 --- a/app/designSystem/landing/LandingFeatures.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' - -type FeatureType = { - heading: string - description: string | any - icon: any -} - -interface Props extends HTMLAttributes { - title: string - subtitle: string - features: FeatureType[] -} - -export const LandingFeatures: React.FC = ({ - title, - subtitle, - features, - className, - ...props -}) => { - return ( -
-
-

- {title} -

-

- {subtitle} -

- -
- {features.map((item, idx) => ( -
-
- {item.icon} -
-
-

{item.heading}

{' '} -

- {item.description} -

-
-
- ))} -
-
-
- ) -} diff --git a/app/designSystem/landing/LandingFooter.tsx b/app/designSystem/landing/LandingFooter.tsx deleted file mode 100644 index 6396e3f..0000000 --- a/app/designSystem/landing/LandingFooter.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Logo } from '@/designSystem/layouts/NavigationLayout/components/Logo' -import { LinkedinFilled, TwitterCircleFilled } from '@ant-design/icons' -import { Link } from '@remix-run/react' -import { HTMLAttributes } from 'react' - -interface Props extends HTMLAttributes {} - -export const LandingFooter: React.FC = ({ ...props }) => { - const socials = [ - { - name: 'X', - icon: , - link: 'https://twitter.com/', - }, - { - name: 'LinkedIn', - icon: , - link: 'https://linkedin.com/', - }, - ] - return ( -
-
-
-
-
- -
-
Copyright © 2024
-
All rights reserved
-
-
-
- {socials.map(link => ( - - {link.name} - - ))} -
-
-
-
-
- ) -} diff --git a/app/designSystem/landing/LandingHero.tsx b/app/designSystem/landing/LandingHero.tsx deleted file mode 100644 index e2bff3e..0000000 --- a/app/designSystem/landing/LandingHero.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { HTMLAttributes, ReactNode } from 'react' -import { DesignSystemUtility } from '../helpers/utility' -import LandingButton from './LandingButton' - -interface Props extends HTMLAttributes { - title: string - subtitle: string - buttonText: string - pictureUrl?: string - socialProof?: ReactNode -} - -export const LandingHero: React.FC = ({ - title, - subtitle, - buttonText, - pictureUrl, - socialProof = '', - className, - ...props -}) => { - return ( -
-
-
-

- {title} -

-

- {subtitle} -

-
- - {buttonText} - -
- {socialProof &&
{socialProof}
} -
- -
- Landing cover -
-
-
- ) -} diff --git a/app/designSystem/landing/LandingHowItWorks.tsx b/app/designSystem/landing/LandingHowItWorks.tsx deleted file mode 100644 index 60b5cac..0000000 --- a/app/designSystem/landing/LandingHowItWorks.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' - -type StepType = { - heading: string - description: string | any -} - -interface Props extends HTMLAttributes { - title: string - subtitle?: string - steps: StepType[] -} - -export const LandingHowItWorks: React.FC = ({ - title, - subtitle = '', - steps, - className, - ...props -}) => { - return ( -
-
-

- {title} -

-
- {steps.map((item, idx) => ( -
-
- {idx + 1} -
-
-

{item.heading}

-

{item.description}

-
-
- ))} -
-
-
- ) -} diff --git a/app/designSystem/landing/LandingNavBar/landing.desktop.navbar.tsx b/app/designSystem/landing/LandingNavBar/landing.desktop.navbar.tsx deleted file mode 100644 index 969951d..0000000 --- a/app/designSystem/landing/LandingNavBar/landing.desktop.navbar.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Logo } from '@/designSystem/layouts/NavigationLayout/components/Logo' - -import { useUserContext } from '@/core/context' -import { ArrowRightOutlined } from '@ant-design/icons' -import LandingButton from '../LandingButton' -import { LandingNavBarItem } from './landing.navbar.items' - -type Props = { - navItems: { - link: string - title: string - target?: '_blank' - }[] -} - -export const LandingDesktopNavbar = ({ navItems }: Props) => { - const { isLoggedIn } = useUserContext() - - return ( -
-
- -
- {navItems.map(item => ( - - {item.title} - - ))} -
-
-
- {isLoggedIn && ( - - Dashboard - - )} - {!isLoggedIn && ( - - Get Started - - )} -
-
- ) -} diff --git a/app/designSystem/landing/LandingNavBar/landing.mobile.navbar.tsx b/app/designSystem/landing/LandingNavBar/landing.mobile.navbar.tsx deleted file mode 100644 index a637325..0000000 --- a/app/designSystem/landing/LandingNavBar/landing.mobile.navbar.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useUserContext } from '@/core/context' -import { Logo } from '@/designSystem/layouts/NavigationLayout/components/Logo' -import { - ArrowRightOutlined, - CloseOutlined, - MenuOutlined, -} from '@ant-design/icons' -import { Link } from '@remix-run/react' -import { useState } from 'react' -import LandingButton from '../LandingButton' - -export const LandingMobileNavbar = ({ navItems }: any) => { - const { isLoggedIn } = useUserContext() - const [open, setOpen] = useState(false) - - return ( -
- - setOpen(!open)} - /> - {open && ( -
-
- -
- setOpen(!open)} - /> -
-
-
- {navItems.map((navItem: any, idx: number) => ( - <> - {navItem.children && navItem.children.length > 0 ? ( - <> - {navItem.children.map((childNavItem: any, idx: number) => ( - setOpen(false)} - className="relative max-w-[15rem] text-left text-2xl" - > - - {childNavItem.title} - - - ))} - - ) : ( - setOpen(false)} - className="relative" - > - - {navItem.title} - - - )} - - ))} -
-
- {isLoggedIn && ( - - Dashboard - - )} - {!isLoggedIn && ( - <> - - Sign Up - - - Login - - - )} -
-
- )} -
- ) -} diff --git a/app/designSystem/landing/LandingNavBar/landing.navbar.items.tsx b/app/designSystem/landing/LandingNavBar/landing.navbar.items.tsx deleted file mode 100644 index 4d99c85..0000000 --- a/app/designSystem/landing/LandingNavBar/landing.navbar.items.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Link, useLocation } from '@remix-run/react' -import { ReactNode } from 'react' -import { DesignSystemUtility } from '../../helpers/utility' - -type Props = { - href: string - children: ReactNode - active?: boolean - className?: string - target?: '_blank' -} - -export function LandingNavBarItem({ - children, - href, - active, - target, - className, -}: Props) { - const pathname = useLocation().pathname - - return ( - - {children} - - ) -} diff --git a/app/designSystem/landing/LandingNavBar/landing.navbar.tsx b/app/designSystem/landing/LandingNavBar/landing.navbar.tsx deleted file mode 100644 index dd7646d..0000000 --- a/app/designSystem/landing/LandingNavBar/landing.navbar.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useDesignSystem } from '~/designSystem/provider' -import { LandingDesktopNavbar } from './landing.desktop.navbar' -import { LandingMobileNavbar } from './landing.mobile.navbar' - -interface Props { - navItems: { - link: string - title: string - target?: '_blank' - }[] -} - -export const LandingNavBar: React.FC = ({ navItems }) => { - const { isMobile } = useDesignSystem() - - return ( -
-
- {!isMobile && } -
-
- {isMobile && } -
-
- ) -} diff --git a/app/designSystem/landing/LandingPainPoints.tsx b/app/designSystem/landing/LandingPainPoints.tsx deleted file mode 100644 index c8b0472..0000000 --- a/app/designSystem/landing/LandingPainPoints.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { ArrowDownOutlined } from '@ant-design/icons' -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' -import RightArrow from './images/rightArrow.svg' - -type PainPointType = { - emoji: string - title: string -} - -interface Props extends HTMLAttributes { - title?: string - subtitle?: string - painPoints: PainPointType[] -} - -export const LandingPainPoints: React.FC = ({ - title, - subtitle, - painPoints, - className, - ...props -}) => { - return ( -
-
-

- {title} -

-

- {subtitle} -

- -
- {painPoints?.map((painPoint, idx) => ( - <> -
-
- {painPoint.emoji} - - {painPoint.title} - -
-
- {idx < painPoints.length - 1 && ( -
- arrow -
- )} - - ))} -
-
-
-

- there is an easier way -

-
-
-
-
- ) -} diff --git a/app/designSystem/landing/LandingPricing.tsx b/app/designSystem/landing/LandingPricing.tsx deleted file mode 100644 index b9804e5..0000000 --- a/app/designSystem/landing/LandingPricing.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { CheckCircleFilled } from '@ant-design/icons' -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' -import LandingButton from './LandingButton' - -type Package = { - title: string - description: string - monthly: number - features: string[] - className?: string - type?: string - highlight?: boolean -} - -interface Props extends HTMLAttributes { - title: string - subtitle: string - packages: Package[] -} - -export const LandingPricing: React.FC = ({ - title, - subtitle, - packages, - className, - ...props -}) => { - return ( -
-
-
-

- {title} -

-

- {subtitle} -

-
- -
- {packages.map((item, idx) => ( - - ))} -
-
-
- ) -} - -const PricingCard = (props: Package) => { - const { title, description, monthly, features, className, type, highlight } = - props - return ( -
-
-
- {highlight && ( - - Popular - - )} - -

- {title} -

-

- $ - {monthly} - - /month - -

-
-
    - {features.map((item, idx) => ( -
  • - - {item} -
  • - ))} -
-
- - {'Get Started'} - -
-
-
- ) -} diff --git a/app/designSystem/landing/LandingRating.tsx b/app/designSystem/landing/LandingRating.tsx deleted file mode 100644 index 9e46147..0000000 --- a/app/designSystem/landing/LandingRating.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { StarFilled, StarOutlined } from '@ant-design/icons' -import clsx from 'clsx' - -/** - * Shows a rating with stars. - */ -export const LandingRating = ({ - className, - rating = 5, - maxRating = 5, - size = 'medium', -}: { - className?: string - rating?: number - maxRating?: number - size?: 'small' | 'medium' | 'large' -}) => { - return ( -
- {Array.from({ length: maxRating }).map((_, index) => { - return ( -
- { - // Return half star for half ratings - rating % 1 !== 0 && - index === Math.floor(rating) && - index + 1 === Math.ceil(rating) ? ( -
-
- ) : ( - = rating, - })} - aria-hidden="true" - /> - ) - } -
- ) - })} -
- ) -} diff --git a/app/designSystem/landing/LandingSocialProof.tsx b/app/designSystem/landing/LandingSocialProof.tsx deleted file mode 100644 index ebff1b4..0000000 --- a/app/designSystem/landing/LandingSocialProof.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { HTMLAttributes } from 'react' - -interface Props extends HTMLAttributes { - title: string -} - -export const LandingSocialProof: React.FC = () => { - const socialProofImages = [ - { url: 'https://i.imgur.com/afwBIFK.png' }, - { url: 'https://i.imgur.com/LlloOPa.png' }, - { url: 'https://i.imgur.com/j8jPb4H.png' }, - { url: 'https://i.imgur.com/mJ1sZFv.png' }, - ] - - return ( -
-
-

- Featured on -

-
- {socialProofImages.map((socialProofImage, idx) => ( - landing social logo - ))} -
-
-
- ) -} diff --git a/app/designSystem/landing/LandingSocialRating.tsx b/app/designSystem/landing/LandingSocialRating.tsx deleted file mode 100644 index 488b60b..0000000 --- a/app/designSystem/landing/LandingSocialRating.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import clsx from 'clsx' -import { LandingAvatar } from './LandingAvatar' -import { LandingRating } from './LandingRating' - -export const LandingSocialRating = ({ - children, - numberOfUsers = 100, - suffixText = 'happy users', -}: { - children?: React.ReactNode - numberOfUsers: number - suffixText?: string -}) => { - const numberText = - numberOfUsers > 1000 - ? `${(numberOfUsers / 1000).toFixed(0)}k` - : `${numberOfUsers}` - - const avatarItems = [ - { - src: 'https://randomuser.me/api/portraits/men/51.jpg', - }, - { - src: 'https://randomuser.me/api/portraits/women/9.jpg', - }, - { - src: 'https://randomuser.me/api/portraits/women/52.jpg', - }, - { - src: 'https://randomuser.me/api/portraits/men/5.jpg', - }, - { - src: 'https://randomuser.me/api/portraits/men/4.jpg', - }, - ] - return ( -
-
- {avatarItems.map((avatarItem, index) => ( - 3 ? `-ml-6` : '', - )} - /> - ))} -
- -
- - - {!children ? ( -

- {numberText}+ {suffixText} -

- ) : ( - children - )} -
-
- ) -} diff --git a/app/designSystem/landing/LandingTestimonials.tsx b/app/designSystem/landing/LandingTestimonials.tsx deleted file mode 100644 index 13e41b3..0000000 --- a/app/designSystem/landing/LandingTestimonials.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { HTMLAttributes } from 'react' -import { DesignSystemUtility } from '../helpers/utility' - -type Testimonial = { - name: string - content: string - designation?: string - avatar?: string -} - -interface Props extends HTMLAttributes { - anchorId?: string - title: string - subtitle: string - testimonials: Testimonial[] -} - -export const LandingTestimonials: React.FC = ({ - title, - subtitle, - testimonials, - className, - ...props -}) => { - return ( -
-
-
-

- {title} -

-

- {subtitle} -

-
- -
- {testimonials.map((testimonial: Testimonial, idx: number) => ( - - ))} -
-
-
- ) -} - -const TestimonialCard = ({ - name, - content, - designation, - avatar, -}: Testimonial) => { - return ( -
-
-
- - -
-

- {name} -

-

- {designation} -

-
-
- -

{content}

-
-
- ) -} diff --git a/app/designSystem/landing/images/linda.webp b/app/designSystem/landing/images/linda.webp new file mode 100644 index 0000000000000000000000000000000000000000..3d64b0613da6b01076fd1ef6dc26464a7cf87127 GIT binary patch literal 97410 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 { - if (data.redirect) { - window.location.href = data.redirect - } - }, - }) - - const errorKey = searchParams.get('error') - - const errorMessage = { - Signin: 'Try signing in with a different account.', - OAuthSignin: 'Try signing in with a different account.', - OAuthCallback: 'Try signing in with a different account.', - OAuthCreateAccount: 'Try signing in with a different account.', - EmailCreateAccount: 'Try signing in with a different account.', - Callback: 'Try signing in with a different account.', - OAuthAccountNotLinked: - 'To confirm your identity, sign in with the same account you used originally.', - EmailSignin: 'Check your email address.', - CredentialsSignin: - 'Sign in failed. Check the details you provided are correct.', - default: 'Unable to sign in.', - }[errorKey ?? 'default'] - - useEffect(() => { - if (process.env.NODE_ENV === 'development') { - form.setFieldValue('email', 'test@test.com') - form.setFieldValue('password', 'password') - } - }, []) - - const handleSubmit = async (values: any) => { - setLoading(true) - - try { - await login({ email: values.email, password: values.password }) - } catch (error) { - console.error(`Could not login: ${error.message}`, { variant: 'error' }) - - setLoading(false) - } - } - - return ( - - - - - {errorKey && ( - {errorMessage} - )} - -
- - - - - - - - - - - - - - - - - -
- - - - -
-
- ) -} diff --git a/app/routes/_auth.register_/route.tsx b/app/routes/_auth.register_/route.tsx deleted file mode 100644 index 8a94b8e..0000000 --- a/app/routes/_auth.register_/route.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { Utility } from '@/core/helpers/utility' -import { Api } from '@/core/trpc' -import { AppHeader } from '@/designSystem/ui/AppHeader' -import { User } from '@prisma/client' -import { useNavigate, useSearchParams } from '@remix-run/react' -import { Button, Flex, Form, Input, Typography } from 'antd' -import { useEffect, useState } from 'react' - -export default function RegisterPage() { - const router = useNavigate() - const [searchParams] = useSearchParams() - - const [form] = Form.useForm() - - const [isLoading, setLoading] = useState(false) - - const { mutateAsync: register } = Api.authentication.register.useMutation() - - const { mutateAsync: login } = Api.authentication.login.useMutation({ - onSuccess: data => { - if (data.redirect) { - window.location.href = data.redirect - } - }, - }) - - useEffect(() => { - const email = searchParams.get('email')?.trim() - - if (Utility.isDefined(email)) { - form.setFieldsValue({ email }) - } - }, [searchParams]) - - const handleSubmit = async (values: Partial) => { - setLoading(true) - - try { - const tokenInvitation = searchParams.get('tokenInvitation') ?? undefined - - await register({ ...values, tokenInvitation }) - - login(values) - } catch (error) { - console.error(`Could not signup: ${error.message}`, { - variant: 'error', - }) - - setLoading(false) - } - } - - return ( - - - - -
- - - - - - - - - - - - - - -
- - -
-
- ) -} diff --git a/app/routes/_auth.reset-password.$token_/route.tsx b/app/routes/_auth.reset-password.$token_/route.tsx deleted file mode 100644 index 03dc591..0000000 --- a/app/routes/_auth.reset-password.$token_/route.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { Api } from '@/core/trpc' -import { AppHeader } from '@/designSystem' -import { useNavigate, useParams } from '@remix-run/react' -import { Alert, Button, Flex, Form, Input, message, Typography } from 'antd' - -const { Text } = Typography - -export default function ResetPasswordTokenPage() { - const router = useNavigate() - - const { token } = useParams<{ token: string }>() - - const [form] = Form.useForm() - - const { - mutateAsync: resetPassword, - isLoading, - isSuccess, - } = Api.authentication.resetPassword.useMutation() - - const handleSubmit = async (values: any) => { - try { - await resetPassword({ token, password: values.password }) - } catch (error) { - message.error(`Could not reset password: ${error.message}`) - } - } - - return ( - <> - - - - - {isSuccess && ( - - )} - - {!isSuccess && ( -
- - - - - - - - - - -
- )} - - - - - or - - - -
-
- - ) -} diff --git a/app/routes/_auth.reset-password_/route.tsx b/app/routes/_auth.reset-password_/route.tsx deleted file mode 100644 index f02b5d5..0000000 --- a/app/routes/_auth.reset-password_/route.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Api } from '@/core/trpc' -import { AppHeader } from '@/designSystem/ui/AppHeader' -import { useNavigate } from '@remix-run/react' -import { Alert, Button, Flex, Form, Input, message, Typography } from 'antd' -import { useState } from 'react' - -const { Text } = Typography - -export default function ResetPasswordPage() { - const navigate = useNavigate() - - const [email, setEmail] = useState() - - const [form] = Form.useForm() - - const { - mutateAsync: resetPassword, - isLoading, - isSuccess, - } = Api.authentication.sendResetPasswordEmail.useMutation() - - const handleSubmit = async (values: any) => { - try { - setEmail(values.email) - - await resetPassword({ email: values.email }) - } catch (error) { - message.error(`Could not reset password: ${error}`) - } - } - - return ( - - - - - {isSuccess && ( - - )} - - {!isSuccess && ( - <> -
- - - - - - -
- - )} - - - - - or - - - -
-
- ) -} diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index fc3fc19..11c1e3c 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,232 +1,25 @@ import { LandingContainer, - LandingCTA, - LandingFAQ, - LandingFeatures, - LandingHero, - LandingHowItWorks, - LandingPainPoints, - LandingPricing, - LandingSocialProof, - LandingSocialRating, - LandingTestimonials, + ChatHistory, + ChatBarForm } from '~/designSystem' export default function LandingPage() { - const features = [ - { - heading: `Smart Task Management`, - description: `Organize and prioritize tasks with intuitive drag-and-drop interfaces and automated workflows.`, - icon: , - }, - { - heading: `Real-Time Collaboration`, - description: `Keep your team aligned with instant updates, comments, and file sharing in one central hub.`, - icon: , - }, - { - heading: `Progress Tracking`, - description: `Get a clear view of project status with visual dashboards, timelines and progress indicators.`, - icon: , - }, - { - heading: `Deadline Management`, - description: `Never miss a deadline with automated reminders and calendar integrations.`, - icon: , - }, - { - heading: `Resource Planning`, - description: `Optimize team workload and resource allocation with capacity planning tools.`, - icon: , - }, - { - heading: `Performance Analytics`, - description: `Make data-driven decisions with detailed project analytics and team performance metrics.`, - icon: , - }, - ] - - const testimonials = [ - { - name: `Sarah Chen`, - designation: `Product Manager at TechFlow`, - content: `Since implementing this platform, our team productivity increased by 45%. Tasks that used to fall through the cracks are now completed on time.`, - avatar: 'https://randomuser.me/api/portraits/women/6.jpg', - }, - { - name: `Mark Thompson`, - designation: `CEO at GrowthLabs`, - content: `The visibility this tool provides has transformed how we manage projects. We've cut meeting time by 60% and improved delivery times.`, - avatar: 'https://randomuser.me/api/portraits/men/7.jpg', - }, - { - name: `Lisa Rodriguez`, - designation: `Team Lead at InnovateCo`, - content: `Finally, a project management tool that's both powerful and easy to use. Our team adopted it within days, not weeks.`, - avatar: 'https://randomuser.me/api/portraits/women/27.jpg', - }, - ] - - const navItems = [ - { - title: `Features`, - link: `#features`, - }, - { - title: `Pricing`, - link: `#pricing`, - }, - { - title: `FAQ`, - link: `#faq`, - }, - ] - - const packages = [ - { - title: `Starter`, - description: `Perfect for small teams getting started`, - monthly: 29, - yearly: 290, - features: [ - `Up to 10 team members`, - `Basic task management`, - `File sharing`, - `Email support`, - ], - }, - { - title: `Professional`, - description: `Ideal for growing businesses`, - monthly: 79, - yearly: 790, - features: [ - `Up to 50 team members`, - `Advanced workflows`, - `Analytics dashboard`, - `Priority support`, - ], - highlight: true, - }, - { - title: `Enterprise`, - description: `For large organizations`, - monthly: 199, - yearly: 1990, - features: [ - `Unlimited team members`, - `Custom integrations`, - `Dedicated success manager`, - `24/7 support`, - ], - }, - ] - - const questionAnswers = [ - { - question: `How quickly can we get started?`, - answer: `You can be up and running in minutes. Our intuitive interface requires minimal training, and we provide comprehensive onboarding resources.`, - }, - { - question: `Can I integrate with other tools?`, - answer: `Yes, we integrate seamlessly with popular tools like Slack, Google Workspace, and Microsoft Office 365.`, - }, - { - question: `What kind of support do you offer?`, - answer: `We provide email support for all plans, with priority support and dedicated success managers for higher tiers.`, - }, - { - question: `Is my data secure?`, - answer: `We use enterprise-grade encryption and regular security audits to ensure your data is always protected.`, - }, - ] - const steps = [ - { - heading: `Sign Up`, - description: `Create your account in minutes and invite your team members.`, - }, - { - heading: `Import Projects`, - description: `Easily import existing projects or start fresh with our templates.`, - }, - { - heading: `Customize Workflow`, - description: `Set up workflows that match your team's unique processes.`, - }, - { - heading: `Track Progress`, - description: `Monitor progress and celebrate team achievements.`, - }, - ] - - const painPoints = [ - { - emoji: `😫`, - title: `Drowning in endless email threads and scattered communications`, - }, - { - emoji: `😤`, - title: `Missing deadlines due to poor task visibility`, - }, - { - emoji: `😩`, - title: `Wasting time in unnecessary status update meetings`, - }, + const messages = [ + { ai: true, text: 'Hello! How can I assist you today?' }, + { ai: false, text: 'I need help with my legal case.' }, + { ai: true, text: 'Sure! Can you provide more details about your case?' }, + { ai: false, text: 'I was involved in a car accident and I want to know my legal options.' }, ] return ( - - - } - /> - - - - - - - - + + ) } diff --git a/app/routes/_logged.home_/route.tsx b/app/routes/_logged.home_/route.tsx deleted file mode 100644 index f36bf88..0000000 --- a/app/routes/_logged.home_/route.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { Typography, Row, Col, Card } from 'antd' -const { Title, Paragraph } = Typography -import { useUserContext } from '@/core/context' -import dayjs from 'dayjs' -import { useLocation, useNavigate, useParams } from '@remix-run/react' -import { useUploadPublic } from '@/plugins/upload/client' -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' - -export default function HomePage() { - const { user } = useUserContext() - - return ( - - - -
- - <i className="las la-home" style={{ marginRight: '0.5rem' }}></i> - Welcome to Our Platform - - - Your one-stop solution for managing organizations and connecting - with others - -
- - - - - - - Personal Space - - {user ? ( - <>Welcome back, {user.name || 'Guest'}! - ) : ( - <>Sign in to access your personal dashboard - )} - - - - - - - - Organizations - - Manage your organizations and collaborate with team members - - - - - - - - Communication - - Stay connected with your team through our integrated chat - system - - - - - - - - Analytics - - Track your progress and monitor important metrics - - - - - - -
-
- ) -} diff --git a/app/routes/_logged.organizations.$organizationId.home_/route.tsx b/app/routes/_logged.organizations.$organizationId.home_/route.tsx deleted file mode 100644 index 8bd202d..0000000 --- a/app/routes/_logged.organizations.$organizationId.home_/route.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { Typography, Card, Space, Row, Col } from 'antd' -const { Title, Text } = Typography -import { useUserContext } from '@/core/context' -import dayjs from 'dayjs' -import { useLocation, useNavigate, useParams } from '@remix-run/react' -import { useUploadPublic } from '@/plugins/upload/client' -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' - -export default function HomePage() { - const { user, organization } = useUserContext() - - return ( - -
- - {/* Welcome Section */} -
- - <i className="las la-home" style={{ marginRight: '12px' }}></i> - Welcome to {organization?.name} - - - Your digital workspace for collaboration and productivity - -
- - {/* Info Cards */} - - - - -
- } - > - - Name: {user?.name} - Email: {user?.email} - - Member since:{' '} - {dayjs(user?.createdAt).format('MMMM D, YYYY')} - - - } - /> - - - - - - - - } - > - - Name: {organization?.name} - - Created:{' '} - {dayjs(organization?.createdAt).format('MMMM D, YYYY')} - - - } - /> - - - - - - - - } - > - - - View Dashboard - - - Team Members - - - Settings - - - } - /> - - - - - -
- ) -} diff --git a/app/routes/_logged.organizations.$organizationId.members_/hooks/useDelete.tsx b/app/routes/_logged.organizations.$organizationId.members_/hooks/useDelete.tsx deleted file mode 100644 index 1ae179a..0000000 --- a/app/routes/_logged.organizations.$organizationId.members_/hooks/useDelete.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useUserContext } from '@/core/context' -import { Api } from '@/core/trpc' -import { OrganizationRole, User } from '@prisma/client' -import { useState } from 'react' -import { useDesignSystem } from '~/designSystem' - -type UserWithOrganizationRoles = User & { - organizationRoles: OrganizationRole[] -} - -type Props = { users: UserWithOrganizationRoles[] } - -export const useDelete = ({ users }: Props) => { - const { message } = useDesignSystem() - - const { user: userLogged, checkOrganizationRole } = useUserContext() - - const [isLoading, setLoading] = useState(false) - - const countOwners = users.filter(user => - user.organizationRoles.find(role => role.name === 'owner'), - ).length - - const { mutateAsync: deleteOrganizationRole } = - Api.organizationRole.deleteMany.useMutation() - - const canDeleteUser = (user: UserWithOrganizationRoles) => { - const isOwner = user.organizationRoles.find( - organizationRole => organizationRole.name === 'owner', - ) - - const isSelf = userLogged.id === user.id - - if (isSelf) { - return !isOwner || countOwners > 1 - } else { - return checkOrganizationRole('owner') - } - } - - const deleteUser = async (user: UserWithOrganizationRoles) => { - setLoading(true) - - let isSuccess = false - - if (canDeleteUser(user)) { - try { - await deleteOrganizationRole({ - where: { - userId: user.id, - }, - }) - - isSuccess = true - - if (user.id === userLogged.id) { - window.location.replace('/') - } else { - message.info(`${user.email} has been removed`) - } - } catch (error) { - message.error(error.message) - } - } - - setLoading(false) - - return isSuccess - } - - return { - deleteUser, - isLoadingDelete: isLoading, - canDeleteUser, - } -} diff --git a/app/routes/_logged.organizations.$organizationId.members_/hooks/useInvitation.tsx b/app/routes/_logged.organizations.$organizationId.members_/hooks/useInvitation.tsx deleted file mode 100644 index 8e8902f..0000000 --- a/app/routes/_logged.organizations.$organizationId.members_/hooks/useInvitation.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Utility } from '@/core/helpers/utility' -import { Api } from '@/core/trpc' -import { Organization } from '@prisma/client' -import { useState } from 'react' -import { useDesignSystem } from '~/designSystem' - -type Props = { - email: string - organization: Organization -} - -export const useInvitation = ({ organization, email }: Props) => { - const { message } = useDesignSystem() - - const [isLoading, setLoading] = useState(false) - - const emailEnsured = email?.trim()?.toLowerCase() - - const { refetch: fetchOrganizationRole } = - Api.organizationRole.findFirst.useQuery( - { - where: { - organizationId: organization.id, - user: { - email: emailEnsured, - }, - }, - }, - { enabled: false }, - ) - - const { mutateAsync: inviteToOrganization } = - Api.authentication.inviteToOrganization.useMutation() - - const invite = async () => { - setLoading(true) - - let isSuccess = false - - if (Utility.isDefined(email)) { - try { - const organizationRole = await fetchOrganizationRole().then( - response => response.data, - ) - - if (!organizationRole) { - await inviteToOrganization({ - organizationId: organization.id, - email: emailEnsured, - }) - - message.info(`${emailEnsured} has been added`) - } - - isSuccess = true - } catch (error) { - message.error(error.message) - } - } - - setLoading(false) - - return isSuccess - } - - return { - invite, - isLoadingInvitation: isLoading, - } -} diff --git a/app/routes/_logged.organizations.$organizationId.members_/hooks/useUpdate.tsx b/app/routes/_logged.organizations.$organizationId.members_/hooks/useUpdate.tsx deleted file mode 100644 index 5f33244..0000000 --- a/app/routes/_logged.organizations.$organizationId.members_/hooks/useUpdate.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useUserContext } from '@/core/context' -import { Api } from '@/core/trpc' -import { useDesignSystem } from '@/designSystem' -import { OrganizationRole, User } from '@prisma/client' -import { useState } from 'react' - -type UserWithOrganizationRoles = User & { - organizationRoles: OrganizationRole[] -} - -type Props = { users: UserWithOrganizationRoles[] } - -export const useUpdate = ({ users }: Props) => { - const { checkOrganizationRole } = useUserContext() - const { message } = useDesignSystem() - - const [isLoading, setLoading] = useState(false) - - const countOwners = users.filter(user => - user.organizationRoles.find(role => role.name === 'owner'), - ).length - - const { mutateAsync: updateOrganizationRole } = - Api.organizationRole.update.useMutation() - - const canUpdate = () => checkOrganizationRole('owner') - - const update = async (organizationRole: OrganizationRole, name: string) => { - setLoading(true) - - let isSuccess = false - - if (canUpdate()) { - try { - const isDowngrade = - organizationRole.name === 'owner' && name !== 'owner' - - if (isDowngrade && countOwners < 2) { - throw new Error(`There must be at least 1 owner`) - } - - await updateOrganizationRole({ - where: { id: organizationRole.id }, - data: { name }, - }) - - isSuccess = true - - message.info(`Role has been updated`) - } catch (error) { - message.error(error.message) - } - } - - setLoading(false) - - return isSuccess - } - - return { - update, - canUpdate, - isLoadingUpdate: isLoading, - } -} diff --git a/app/routes/_logged.organizations.$organizationId.members_/route.tsx b/app/routes/_logged.organizations.$organizationId.members_/route.tsx deleted file mode 100644 index 7c4bbcb..0000000 --- a/app/routes/_logged.organizations.$organizationId.members_/route.tsx +++ /dev/null @@ -1,300 +0,0 @@ -import { - Avatar, - Button, - Dropdown, - Flex, - Form, - Input, - MenuProps, - Popconfirm, - Row, - Table, - TableProps, - Tag, - Tooltip, - Typography, -} from 'antd' - -import { useUserContext } from '@/core/context' -import { Utility } from '@/core/helpers/utility' -import { Api } from '@/core/trpc' -import { PageLayout, useDesignSystem } from '@/designSystem' -import { - CheckOutlined, - CopyOutlined, - DeleteOutlined, - EditFilled, - HourglassOutlined, - UserAddOutlined, -} from '@ant-design/icons' -import { OrganizationRole, User } from '@prisma/client' -import { useState } from 'react' -import { useDelete } from './hooks/useDelete' -import { useInvitation } from './hooks/useInvitation' -import { useUpdate } from './hooks/useUpdate' - -type UserWithOrganizationRoles = User & { - organizationRoles: OrganizationRole[] -} - -export default function OrganizationTeamPage() { - const { organization } = useUserContext() - const { message } = useDesignSystem() - - const [form] = Form.useForm() - - const [email, setEmail] = useState('') - - const { - data: users, - isLoading: isLoadingUsers, - refetch: refetchUsers, - } = Api.user.findMany.useQuery( - { - where: { - organizationRoles: { some: { organizationId: organization.id } }, - }, - include: { - organizationRoles: { where: { organizationId: organization.id } }, - }, - orderBy: { createdAt: 'desc' }, - }, - { initialData: [] }, - ) - - const { invite, isLoadingInvitation } = useInvitation({ organization, email }) - - const { update, canUpdate, isLoadingUpdate } = useUpdate({ users }) - - const { deleteUser, canDeleteUser, isLoadingDelete } = useDelete({ users }) - - const handleInvite = async () => { - const isSuccess = await invite() - - if (isSuccess) { - setEmail('') - form.setFieldsValue({ email: '' }) - refetchUsers() - } - } - - const handleUpdate = async ( - organizationRole: OrganizationRole, - name: string, - ) => { - const isSuccess = await update(organizationRole, name) - - if (isSuccess) { - refetchUsers() - } - } - - const handleDeleteUser = async (user: UserWithOrganizationRoles) => { - const isSuccess = await deleteUser(user) - - if (isSuccess) { - refetchUsers() - } - } - - const dataSource = users - .map(item => ({ ...item, key: item.id })) - .filter(item => { - const search = email.trim().toLowerCase() - const userEmail = item.email.trim().toLowerCase() - const userName = item.name?.trim().toLowerCase() ?? '' - - return userEmail.includes(search) || userName.includes(search) - }) - - const columns: TableProps['columns'] = [ - { - title: `${dataSource.length} Members`, - key: 'id', - render: (user: UserWithOrganizationRoles) => ( - - - {Utility.stringToInitials(user.name ?? user.email)} - - - - {user.name} - - {user.email} - - - - ), - }, - { - title: 'Role', - key: 'role', - render: (user: UserWithOrganizationRoles) => ( - - {user.organizationRoles.map(role => { - const isInvited = user.status === 'INVITED' - - const isUserOwner = role.name === 'owner' - - const itemsDropdown: MenuProps['items'] = [ - { - key: 'owner', - label: ( - Owner {isUserOwner && } - ), - onClick: () => handleUpdate(role, 'owner'), - }, - { - key: 'member', - label: ( - - Member {!isUserOwner && } - - ), - onClick: () => handleUpdate(role, 'member'), - }, - ] - - return ( - - - {isInvited && } - - {role.name} - - {canUpdate() && ( - - - - )} - - - ) - })} - - ), - }, - { - title: '', - key: 'invite', - width: '50px', - render: (user: UserWithOrganizationRoles) => { - return ( - - {user.status === 'INVITED' && ( - - - } - /> - - - - - - - ) -} diff --git a/app/routes/_logged.organizations.$organizationId.pricing_/route.tsx b/app/routes/_logged.organizations.$organizationId.pricing_/route.tsx deleted file mode 100644 index e252d55..0000000 --- a/app/routes/_logged.organizations.$organizationId.pricing_/route.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { Card, Col, Empty, Flex, Row, Spin, Tag, Typography } from 'antd' - -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' -import { Product } from '@/plugins/payment/server' -import { useParams } from '@remix-run/react' - -export default function OrganizationPricingPage() { - const params = useParams<{ organizationId: string }>() - - const { data: products, isLoading: isLoadingProducts } = - Api.billing.findManyProducts.useQuery({}, { initialData: [] }) - - const { mutateAsync: createPaymentLink } = - Api.billing.createPaymentLink.useMutation() - - const { data: subscriptions } = Api.billing.findManySubscriptions.useQuery( - { - organizationId: params.organizationId, - }, - { initialData: [] }, - ) - - const handleClick = async (product: Product) => { - const { url } = await createPaymentLink({ - productId: product.id, - organizationId: params.organizationId, - }) - - window.open(url, '_blank') - } - - const getPrice = (product: Product) => { - if (product.price === 0) { - return 'Free' - } - - const mapping = { - usd: '${{price}}', - } - - const pattern = mapping[product.currency] - - if (pattern) { - return pattern.replace('{{price}}', product.price) - } - - return `${product.currency.toUpperCase()} ${product.price}` - } - - const isSubscribed = (product: Product) => { - return subscriptions.find( - subscription => subscription.productId === product.id, - ) - } - - return ( - - - {products.length === 0 && isLoadingProducts && } - - {products.length === 0 && !isLoadingProducts && ( - - )} - - {products.map(product => ( - - handleClick(product)} - cover={ - - {product.name} - - } - > - - - {product.name} - - - - - {getPrice(product)} - - {product.interval && ( - - / {product.interval} - - )} - - - {isSubscribed(product) && ( -
- Active -
- )} - - - {product.description} - -
-
- - ))} - - - ) -} diff --git a/app/routes/_logged.organizations.$organizationId.settings_/route.tsx b/app/routes/_logged.organizations.$organizationId.settings_/route.tsx deleted file mode 100644 index f088a17..0000000 --- a/app/routes/_logged.organizations.$organizationId.settings_/route.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Avatar, Button, Flex, Form, Input, message, Popconfirm } from 'antd' - -import { useUserContext } from '@/core/context' -import { Utility } from '@/core/helpers/utility' -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' -import { User } from '@prisma/client' -import { useEffect } from 'react' - -export default function OrganizationSettingsPage() { - const { - organization, - refetchOrganization, - refetchOrganizations, - checkOrganizationRole, - } = useUserContext() - - const { mutateAsync: updateOrganization, isLoading: isLoadingUpdate } = - Api.organization.update.useMutation() - - const { mutateAsync: deleteOrganization, isLoading: isLoadingDelete } = - Api.organization.delete.useMutation() - - const [form] = Form.useForm() - - useEffect(() => { - form.setFieldsValue(organization) - }, [organization]) - - const handleSubmit = async (values: Partial) => { - try { - await updateOrganization({ - where: { id: organization.id }, - data: { - name: values.name, - pictureUrl: values.pictureUrl, - }, - }) - - refetchOrganization() - refetchOrganizations() - } catch (error) { - message.error(`Could not save user: ${error.message}`) - } - } - - const handleClickDelete = async () => { - await deleteOrganization({ where: { id: organization.id } }) - - window.location.replace('/home') - } - - return ( - - - - {Utility.stringToInitials(organization.name)[0]} - - - -
- - - - - - - - - - - - - - - - {checkOrganizationRole('owner') && ( - - - - - - )} -
- ) -} diff --git a/app/routes/_logged.organizations/route.tsx b/app/routes/_logged.organizations/route.tsx deleted file mode 100644 index e4a2646..0000000 --- a/app/routes/_logged.organizations/route.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useUserContext } from '@/core/context' -import { MrbSplashScreen } from '@/designSystem' -import { Outlet } from '@remix-run/react' -import { useEffect } from 'react' - -export default function OrganizationsLayout() { - const { isLoadingOrganization, organization } = useUserContext() - - useEffect(() => { - if (!isLoadingOrganization && !organization) { - window.location.replace('/') - } - }, [isLoadingOrganization, organization]) - - if (isLoadingOrganization) { - return - } - - if (organization) { - return - } -} diff --git a/app/routes/_logged.pricing_/route.tsx b/app/routes/_logged.pricing_/route.tsx deleted file mode 100644 index 1612944..0000000 --- a/app/routes/_logged.pricing_/route.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { Card, Col, Empty, Flex, Row, Spin, Tag, Typography } from 'antd' - -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' -import { Product } from '~/plugins/payment/server' - -export default function PricingPage() { - const { data: products, isLoading: isLoadingProducts } = - Api.billing.findManyProducts.useQuery({}, { initialData: [] }) - - const { mutateAsync: createPaymentLink } = - Api.billing.createPaymentLink.useMutation() - - const { data: subscriptions } = Api.billing.findManySubscriptions.useQuery( - {}, - { initialData: [] }, - ) - - const handleClick = async (product: Product) => { - const { url } = await createPaymentLink({ productId: product.id }) - - window.open(url, '_blank') - } - - const getPrice = (product: Product) => { - if (product.price === 0) { - return 'Free' - } - - const mapping = { - usd: '${{price}}', - } - - const pattern = mapping[product.currency] - - if (pattern) { - return pattern.replace('{{price}}', product.price) - } - - return `${product.currency.toUpperCase()} ${product.price}` - } - - const isSubscribed = (product: Product) => { - return subscriptions.find( - subscription => subscription.productId === product.id, - ) - } - - return ( - - - {products.length === 0 && isLoadingProducts && } - - {products.length === 0 && !isLoadingProducts && ( - - )} - - {products.map(product => ( -
- handleClick(product)} - cover={ - - {product.name} - - } - > - - - {product.name} - - - - - {getPrice(product)} - - {product.interval && ( - - / {product.interval} - - )} - - - {isSubscribed(product) && ( -
- Active -
- )} - - - {product.description} - -
-
- - ))} - - - ) -} diff --git a/app/routes/_logged.profile_/route.tsx b/app/routes/_logged.profile_/route.tsx deleted file mode 100644 index 7801464..0000000 --- a/app/routes/_logged.profile_/route.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { Avatar, Button, Flex, Form, Input, Typography } from 'antd' - -import { useUserContext } from '@/core/context' -import { Utility } from '@/core/helpers/utility' -import { Api } from '@/core/trpc' -import { PageLayout } from '@/designSystem' -import { User } from '@prisma/client' -import { useEffect, useState } from 'react' - -export default function ProfilePage() { - const { user, refetch: refetchUser } = useUserContext() - const { mutateAsync: logout } = Api.authentication.logout.useMutation({ - onSuccess: data => { - if (data.redirect) { - window.location.href = data.redirect - } - }, - }) - - const [form] = Form.useForm() - - const [isLoading, setLoading] = useState(false) - const [isLoadingLogout, setLoadingLogout] = useState(false) - - const { mutateAsync: updateUser } = Api.user.update.useMutation() - - useEffect(() => { - form.setFieldsValue(user) - }, [user]) - - const handleSubmit = async (values: Partial) => { - setLoading(true) - - try { - await updateUser({ - where: { id: user.id }, - data: { - email: values.email, - name: values.name, - pictureUrl: values.pictureUrl, - }, - }) - - refetchUser() - } catch (error) { - console.error(`Could not save user: ${error.message}`, { - variant: 'error', - }) - } - - setLoading(false) - } - - const handleClickLogout = async () => { - setLoadingLogout(true) - - try { - await logout() - } catch (error) { - console.error(`Could not logout: ${error.message}`, { - variant: 'error', - }) - - setLoadingLogout(false) - } - } - - return ( - - - Profile - - - - - - {Utility.stringToInitials(user?.name)} - - - -
- - - - - - - - - - - - - - - - - - -
- ) -} diff --git a/app/routes/hooks/handleChat.tsx b/app/routes/hooks/handleChat.tsx new file mode 100644 index 0000000..e69de29 From fb83f2bbd207a60fede576f368757b974fcfe1e5 Mon Sep 17 00:00:00 2001 From: Amjad Marblism Date: Wed, 18 Feb 2026 14:25:08 +0000 Subject: [PATCH 2/4] chore : basic api methods, chat is working now refacto : clean other front page --- app/designSystem/landing/ChatBarForm.tsx | 48 ++++++++--------- .../providers/openai/openai.provider.ts | 53 ++++++++++++++++++- app/routes/_index.tsx | 22 ++++++-- app/routes/_logged.tsx | 29 ---------- 4 files changed, 91 insertions(+), 61 deletions(-) delete mode 100644 app/routes/_logged.tsx diff --git a/app/designSystem/landing/ChatBarForm.tsx b/app/designSystem/landing/ChatBarForm.tsx index bfa1f2e..3492a0b 100644 --- a/app/designSystem/landing/ChatBarForm.tsx +++ b/app/designSystem/landing/ChatBarForm.tsx @@ -1,48 +1,42 @@ import { InputHTMLAttributes, useState } from 'react' import { Api } from '~/core/trpc' -interface ChatBarFormProps extends InputHTMLAttributes {} +interface ChatBarFormProps extends InputHTMLAttributes { + onNewMessage: (message: any) => void +} /** * Form component for the chat input bar, allowing users to type and submit messages. */ export const ChatBarForm = ({ className, + onNewMessage, ...remainingProps }: ChatBarFormProps) => { - const login = Api.authentication.login.useMutation() + const { mutateAsync:login } = Api.authentication.login.useMutation(); + const { mutateAsync:generateText } = Api.ai.generateText.useMutation(); + + const handleLogin = async () => { + await login({ + email: 'test@test.com', + password: 'password', + }); + }; - const generateText = Api.ai.generateText.useMutation() + const handleGenerateText = async (promptMessage: string) => { + return generateText({prompt: promptMessage}) + }; const [message, setMessage] = useState('') const handleSubmit = async (event: React.FormEvent) => { + onNewMessage({ ai: false, text: message }); event.preventDefault() - const user = await login.mutateAsync({ - email: 'test@test.com', - password: 'password', - }, { - onSuccess: (data) => { - console.log('Login successful:', data)} - }); - - console.log(JSON.stringify(user)) - console.log(message) - generateText.context = { - userId: '12345', - sessionId: 'abcde', - } - console.log(generateText.context) - await generateText.mutateAsync({ - prompt: message, - attachmentUrls: [], - provider: 'openai' - }).then((response) => { - console.log('AI response:', response) - }).catch((error) => { - console.error('Error generating text:', error) - }); + await handleLogin(); // Handle form submission logic here + await handleGenerateText(message).then((response) => { + onNewMessage({ ai: true, text: response.answer }); + }); setMessage(''); } diff --git a/app/plugins/ai/server/providers/openai/openai.provider.ts b/app/plugins/ai/server/providers/openai/openai.provider.ts index cd67404..55c2df1 100644 --- a/app/plugins/ai/server/providers/openai/openai.provider.ts +++ b/app/plugins/ai/server/providers/openai/openai.provider.ts @@ -1,9 +1,13 @@ +import { response } from 'express' import { ReadStream } from 'fs' import OpenaiSDK from 'openai' import { zodResponseFormat } from 'openai/helpers/zod' import { ParsedChatCompletion } from 'openai/resources/beta/chat/completions' import { z, ZodType } from 'zod' +type Message = OpenaiSDK.Chat.Completions.ChatCompletionMessageParam +type Response = OpenaiSDK.Chat.Completions.ChatCompletion + export type OpenaiGenerateTextOptions = { prompt: string attachmentUrls?: string[] @@ -22,7 +26,7 @@ enum OpenaiModel { type BuildMessageOptions = { content: string attachmentUrls?: string[] - history?: string[] + history?: Message[] context?: string } @@ -59,7 +63,52 @@ export class OpenaiProvider { } async generateText(options: OpenaiGenerateTextOptions): Promise { - return + const { + prompt, + attachmentUrls, + history, + context, + } = options + + const messages : Message[] = this.buildMessages(); + const response : Response = await this.createResponse(options, messages); + const content = response.choices[0].message?.content as string + return content; + } + + private buildMessages(options?: BuildMessageOptions): Message[] { + const { content, context, history } = options || {}; + const messages: Message[] = []; + + const promptSystem = { + role: 'system', + content: `${context}`.trim(), + } + + messages.push(promptSystem as Message) + if(history){ messages.push(...history) } + if(content) { + messages.push({ + role: 'user', + content: [ {type:'text', text: `${content}`.trim()} ] + } as Message) + } + + return messages + } + + private createResponse(options: OpenaiGenerateTextOptions, messages: Message[]): Promise { + const { prompt } = options + return this.api.chat.completions.create({ + model: OpenaiModel.DEFAULT, + messages: [ + ...messages, + { + role: 'user', + content: `${prompt}`.trim(), + } as Message, + ] + }) } async generateJson< diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index 11c1e3c..4291f2c 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,17 +1,33 @@ +import { useState } from 'react' import { LandingContainer, ChatHistory, ChatBarForm } from '~/designSystem' +type ChatMessage = { + ai: boolean + text: string +} + export default function LandingPage() { - const messages = [ + const handleNewMessage = (newMessage: ChatMessage) => { + console.log('New message:', newMessage); + setMessages((chats) => { + chats.push(newMessage) + return [...chats] + }); + console.log('Updated messages:', messages); + // Here you can add the logic to send the message to your AI service and update the chat history with the response. + } + + const [messages, setMessages] = useState([ { ai: true, text: 'Hello! How can I assist you today?' }, { ai: false, text: 'I need help with my legal case.' }, { ai: true, text: 'Sure! Can you provide more details about your case?' }, { ai: false, text: 'I was involved in a car accident and I want to know my legal options.' }, - ] + ]) return ( @@ -19,7 +35,7 @@ export default function LandingPage() { title={`Legal Assistant Chat`} messages={messages} /> - + ) } diff --git a/app/routes/_logged.tsx b/app/routes/_logged.tsx deleted file mode 100644 index d0b0799..0000000 --- a/app/routes/_logged.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useUserContext } from '@/core/context' -import { NavigationLayout } from '@/designSystem/layouts/NavigationLayout' -import { Outlet, useNavigate } from '@remix-run/react' -import { useEffect } from 'react' -import { MrbSplashScreen } from '~/designSystem' - -export default function LoggedLayout() { - const { isLoggedIn, isLoading } = useUserContext() - - const router = useNavigate() - - useEffect(() => { - if (!isLoading && !isLoggedIn) { - router('/login') - } - }, [isLoading, isLoggedIn]) - - if (isLoading) { - return - } - - if (isLoggedIn) { - return ( - - - - ) - } -} From b0b8a01a0eb3605235a658ae0565c63f68c3ec9a Mon Sep 17 00:00:00 2001 From: Amjad Marblism Date: Wed, 18 Feb 2026 15:27:18 +0000 Subject: [PATCH 3/4] fix : chat behaviour chore : adding pdf rule as a guideline --- app/designSystem/landing/ChatBarForm.tsx | 13 +++++--- app/designSystem/landing/ChatHistory.tsx | 32 +++++++++++++++---- .../providers/openai/openai.provider.ts | 19 ++++++++--- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/designSystem/landing/ChatBarForm.tsx b/app/designSystem/landing/ChatBarForm.tsx index 3492a0b..15215d4 100644 --- a/app/designSystem/landing/ChatBarForm.tsx +++ b/app/designSystem/landing/ChatBarForm.tsx @@ -32,12 +32,17 @@ export const ChatBarForm = ({ const handleSubmit = async (event: React.FormEvent) => { onNewMessage({ ai: false, text: message }); event.preventDefault() + setMessage(''); await handleLogin(); // Handle form submission logic here await handleGenerateText(message).then((response) => { - onNewMessage({ ai: true, text: response.answer }); + if(response.answer.includes('') && response.answer.includes('')) { + const pdfFile = response.answer.split('')[1].split('')[0]; + onNewMessage({ ai: true, text: 'Here is the pdf!', pdfFile }); + } else { + onNewMessage({ ai: true, text: response.answer }); + } }); - setMessage(''); } const handleChange = (event: React.ChangeEvent) => { @@ -45,11 +50,11 @@ export const ChatBarForm = ({ }; return ( -
+ diff --git a/app/designSystem/landing/ChatHistory.tsx b/app/designSystem/landing/ChatHistory.tsx index 07d9650..39ab564 100644 --- a/app/designSystem/landing/ChatHistory.tsx +++ b/app/designSystem/landing/ChatHistory.tsx @@ -13,7 +13,8 @@ interface Props extends HTMLAttributes { interface MessageHistory { ai: boolean - text: string + text: string, + pdfFile?: string } export const ChatHistory: React.FC = ({ @@ -25,21 +26,40 @@ export const ChatHistory: React.FC = ({ className, ...props }) => { + + const handleDownload = (index) => { + const pdfFile = messages[index].pdfFile; + if (pdfFile) { + const link = document.createElement('a'); + link.href = pdfFile; + link.download = `file-${index}.pdf`; + link.click(); + } + } + return (
-
-

{title}

-
+
+

{title}

+
{messages.map((message,index) => ( -
+ ))}
diff --git a/app/plugins/ai/server/providers/openai/openai.provider.ts b/app/plugins/ai/server/providers/openai/openai.provider.ts index 55c2df1..dcffd8f 100644 --- a/app/plugins/ai/server/providers/openai/openai.provider.ts +++ b/app/plugins/ai/server/providers/openai/openai.provider.ts @@ -80,12 +80,21 @@ export class OpenaiProvider { const { content, context, history } = options || {}; const messages: Message[] = []; - const promptSystem = { - role: 'system', - content: `${context}`.trim(), - } + const promptSystem: Message = { + role: 'system', + content: `${context}`.trim(), + } + + const guideline: Message = { + role: 'system', + content: ` + If the user request a pdf file, you should answer with 'Here is the pdf!', + and then with the potential content of the pdf encapsulated with . + ` + } - messages.push(promptSystem as Message) + messages.push(promptSystem as Message); + messages.push(guideline as Message); if(history){ messages.push(...history) } if(content) { messages.push({ From de265fa188fc3370d73a7b0ea220ce6e5de11618 Mon Sep 17 00:00:00 2001 From: Amjad Marblism Date: Wed, 18 Feb 2026 15:50:20 +0000 Subject: [PATCH 4/4] deps : add jspdf chore : added scroll to bot and kicked a part of the mock --- app/designSystem/landing/ChatHistory.tsx | 14 +- app/routes/_index.tsx | 6 +- package.json | 2 + pnpm-lock.yaml | 214 ++++++++++++++++++++++- 4 files changed, 226 insertions(+), 10 deletions(-) diff --git a/app/designSystem/landing/ChatHistory.tsx b/app/designSystem/landing/ChatHistory.tsx index 39ab564..3c1641d 100644 --- a/app/designSystem/landing/ChatHistory.tsx +++ b/app/designSystem/landing/ChatHistory.tsx @@ -2,6 +2,7 @@ import { HTMLAttributes } from 'react' import { DesignSystemUtility } from '../helpers/utility' import LandingButton from './LandingButton' import { LandingAvatar } from './LandingAvatar' +import { jsPDF } from 'jspdf' interface Props extends HTMLAttributes { messages: MessageHistory[] @@ -30,10 +31,15 @@ export const ChatHistory: React.FC = ({ const handleDownload = (index) => { const pdfFile = messages[index].pdfFile; if (pdfFile) { + const doc = new jsPDF(); + doc.text(pdfFile, 10, 10); + const pdfBlob = doc.output('blob'); + const url = window.URL.createObjectURL(pdfBlob); const link = document.createElement('a'); - link.href = pdfFile; - link.download = `file-${index}.pdf`; + link.href = url; + link.target = '_blank'; link.click(); + window.URL.revokeObjectURL(url); } } @@ -44,7 +50,9 @@ export const ChatHistory: React.FC = ({ >

{title}

-
+
{messages.map((message,index) => (
([ - { ai: true, text: 'Hello! How can I assist you today?' }, - { ai: false, text: 'I need help with my legal case.' }, - { ai: true, text: 'Sure! Can you provide more details about your case?' }, - { ai: false, text: 'I was involved in a car accident and I want to know my legal options.' }, + { ai: true, text: 'Hello! How can I assist you today?' } ]) return ( diff --git a/package.json b/package.json index 2663d01..5dfd143 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "isbot": "^4.1.0", "jsonwebtoken": "8.5.1", "jsonwebtoken-esm": "1.0.5", + "jspdf": "^4.1.0", "morgan": "^1.10.0", "node-cron": "^3.0.3", "node-mailjet": "^6.0.6", @@ -89,6 +90,7 @@ "@types/cookie": "^1.0.0", "@types/express": "^5.0.0", "@types/jsonwebtoken": "^9.0.7", + "@types/jspdf": "^2.0.0", "@types/node-cron": "^3.0.11", "@types/nodemailer": "^6.4.16", "@types/passport": "^1.0.16", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b95ebc..bc9b5a8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,6 +101,9 @@ importers: jsonwebtoken-esm: specifier: 1.0.5 version: 1.0.5 + jspdf: + specifier: ^4.1.0 + version: 4.1.0 morgan: specifier: ^1.10.0 version: 1.10.0 @@ -192,6 +195,9 @@ importers: '@types/jsonwebtoken': specifier: ^9.0.7 version: 9.0.7 + '@types/jspdf': + specifier: ^2.0.0 + version: 2.0.0 '@types/node-cron': specifier: ^3.0.11 version: 3.0.11 @@ -590,6 +596,10 @@ packages: resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.25.0': resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} @@ -1252,67 +1262,79 @@ packages: resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.5': resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.4': resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.4': resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.4': resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.4': resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.33.5': resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.33.5': resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.33.5': resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.33.5': resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.5': resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.33.5': resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.33.5': resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} @@ -1616,46 +1638,55 @@ packages: resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.22.4': resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.22.4': resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.22.4': resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.22.4': resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.22.4': resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.22.4': resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.22.4': resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.22.4': resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} @@ -1992,6 +2023,10 @@ packages: '@types/jsonwebtoken@9.0.7': resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} + '@types/jspdf@2.0.0': + resolution: {integrity: sha512-oonYDXI4GegGaG7FFVtriJ+Yqlh4YR3L3NVDiwCEBVG7sbya19SoGx4MW4kg1MCMRPgkbbFTck8YKJL8PrkDfA==} + deprecated: This is a stub types definition. jspdf provides its own type definitions, so you do not need this installed. + '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -2022,6 +2057,9 @@ packages: '@types/nodemailer@6.4.16': resolution: {integrity: sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==} + '@types/pako@2.0.4': + resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==} + '@types/passport@1.0.16': resolution: {integrity: sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==} @@ -2031,6 +2069,9 @@ packages: '@types/qs@6.9.16': resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} + '@types/raf@3.4.3': + resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==} + '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -2049,6 +2090,9 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2299,6 +2343,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -2397,6 +2445,10 @@ packages: caniuse-lite@1.0.30001663: resolution: {integrity: sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==} + canvg@3.0.11: + resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==} + engines: {node: '>=10.0.0'} + capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -2573,6 +2625,9 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + core-js@3.48.0: + resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2580,6 +2635,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2760,6 +2818,9 @@ packages: dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dompurify@3.3.1: + resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -3049,6 +3110,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-png@6.4.0: + resolution: {integrity: sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==} + fast-xml-parser@4.4.1: resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} hasBin: true @@ -3065,6 +3129,9 @@ packages: fflate@0.4.8: resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3290,6 +3357,10 @@ packages: resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -3355,6 +3426,9 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + iobuffer@5.4.0: + resolution: {integrity: sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -3614,6 +3688,9 @@ packages: resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==} engines: {node: '>=4', npm: '>=1.4.28'} + jspdf@4.1.0: + resolution: {integrity: sha512-xd1d/XRkwqnsq6FP3zH1Q+Ejqn2ULIJeDZ+FTKpaabVpZREjsJKRJwuokTNgdqOU+fl55KgbvgZ1pRTSWCP2kQ==} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -4158,6 +4235,9 @@ packages: pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + papaparse@5.4.1: resolution: {integrity: sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==} @@ -4239,6 +4319,9 @@ packages: peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} @@ -4433,6 +4516,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -4745,6 +4831,9 @@ packages: resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} engines: {node: '>= 0.4'} + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -4808,6 +4897,10 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rgbcolor@1.0.1: + resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==} + engines: {node: '>= 0.8.15'} + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -5095,6 +5188,10 @@ packages: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + stackblur-canvas@2.7.0: + resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==} + engines: {node: '>=0.1.14'} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -5216,6 +5313,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-pathdata@6.0.3: + resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} + engines: {node: '>=12.0.0'} + tailwind-merge@2.5.2: resolution: {integrity: sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==} @@ -5248,6 +5349,9 @@ packages: engines: {node: '>=10'} hasBin: true + text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -5481,6 +5585,9 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true @@ -6479,6 +6586,8 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@babel/runtime@7.28.6': {} + '@babel/template@7.25.0': dependencies: '@babel/code-frame': 7.24.7 @@ -7825,6 +7934,10 @@ snapshots: dependencies: '@types/node': 22.6.1 + '@types/jspdf@2.0.0': + dependencies: + jspdf: 4.1.0 + '@types/mdast@3.0.15': dependencies: '@types/unist': 2.0.11 @@ -7858,6 +7971,8 @@ snapshots: dependencies: '@types/node': 22.6.1 + '@types/pako@2.0.4': {} + '@types/passport@1.0.16': dependencies: '@types/express': 5.0.0 @@ -7866,6 +7981,9 @@ snapshots: '@types/qs@6.9.16': {} + '@types/raf@3.4.3': + optional: true + '@types/range-parser@1.2.7': {} '@types/react-dom@18.3.1': @@ -7890,6 +8008,9 @@ snapshots: '@types/node': 22.6.1 '@types/send': 0.17.4 + '@types/trusted-types@2.0.7': + optional: true + '@types/unist@2.0.11': {} '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': @@ -8330,6 +8451,9 @@ snapshots: balanced-match@1.0.2: {} + base64-arraybuffer@1.0.2: + optional: true + base64-js@1.5.1: {} base64url@3.0.1: {} @@ -8449,6 +8573,18 @@ snapshots: caniuse-lite@1.0.30001663: {} + canvg@3.0.11: + dependencies: + '@babel/runtime': 7.28.6 + '@types/raf': 3.4.3 + core-js: 3.48.0 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + rgbcolor: 1.0.1 + stackblur-canvas: 2.7.0 + svg-pathdata: 6.0.3 + optional: true + capital-case@1.0.4: dependencies: no-case: 3.0.4 @@ -8633,6 +8769,9 @@ snapshots: dependencies: toggle-selection: 1.0.6 + core-js@3.48.0: + optional: true + core-util-is@1.0.3: {} cross-spawn@7.0.3: @@ -8641,6 +8780,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-line-break@2.1.0: + dependencies: + utrie: 1.0.2 + optional: true + css-what@6.1.0: {} cssesc@3.0.0: {} @@ -8782,6 +8926,11 @@ snapshots: '@babel/runtime': 7.25.6 csstype: 3.1.3 + dompurify@3.3.1: + optionalDependencies: + '@types/trusted-types': 2.0.7 + optional: true + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -9059,7 +9208,7 @@ snapshots: debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-plugin-import@2.30.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 @@ -9072,7 +9221,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-plugin-import@2.30.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -9094,7 +9243,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-plugin-import@2.30.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -9317,6 +9466,12 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-png@6.4.0: + dependencies: + '@types/pako': 2.0.4 + iobuffer: 5.4.0 + pako: 2.1.0 + fast-xml-parser@4.4.1: dependencies: strnum: 1.0.5 @@ -9335,6 +9490,8 @@ snapshots: fflate@0.4.8: {} + fflate@0.8.2: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -9588,6 +9745,12 @@ snapshots: dependencies: lru-cache: 7.18.3 + html2canvas@1.4.1: + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + optional: true + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -9649,6 +9812,8 @@ snapshots: internmap@2.0.3: {} + iobuffer@5.4.0: {} + ipaddr.js@1.9.1: {} is-alphabetical@2.0.1: {} @@ -9874,6 +10039,17 @@ snapshots: ms: 2.1.3 semver: 5.7.2 + jspdf@4.1.0: + dependencies: + '@babel/runtime': 7.28.6 + fast-png: 6.4.0 + fflate: 0.8.2 + optionalDependencies: + canvg: 3.0.11 + core-js: 3.48.0 + dompurify: 3.3.1 + html2canvas: 1.4.1 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.8 @@ -10608,6 +10784,8 @@ snapshots: pako@0.2.9: {} + pako@2.1.0: {} + papaparse@5.4.1: {} param-case@3.0.4: @@ -10693,6 +10871,9 @@ snapshots: duplexify: 3.7.1 through2: 2.0.5 + performance-now@2.1.0: + optional: true + periscopic@3.1.0: dependencies: '@types/estree': 1.0.6 @@ -10877,6 +11058,11 @@ snapshots: queue-microtask@1.2.3: {} + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + optional: true + range-parser@1.2.1: {} raw-body@2.5.2: @@ -11304,6 +11490,9 @@ snapshots: globalthis: 1.0.4 which-builtin-type: 1.1.4 + regenerator-runtime@0.13.11: + optional: true + regenerator-runtime@0.14.1: {} regexp-to-ast@0.5.0: {} @@ -11382,6 +11571,9 @@ snapshots: reusify@1.0.4: {} + rgbcolor@1.0.1: + optional: true + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -11695,6 +11887,9 @@ snapshots: dependencies: minipass: 7.1.2 + stackblur-canvas@2.7.0: + optional: true + statuses@2.0.1: {} stream-shift@1.0.3: {} @@ -11835,6 +12030,9 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-pathdata@6.0.3: + optional: true + tailwind-merge@2.5.2: {} tailwindcss@3.4.13: @@ -11903,6 +12101,11 @@ snapshots: source-map-support: 0.5.21 optional: true + text-segmentation@1.0.3: + dependencies: + utrie: 1.0.2 + optional: true + text-table@0.2.0: {} thenify-all@1.6.0: @@ -12154,6 +12357,11 @@ snapshots: utils-merge@1.0.1: {} + utrie@1.0.2: + dependencies: + base64-arraybuffer: 1.0.2 + optional: true + uuid@10.0.0: {} uuid@8.3.2: {}