Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor & added animations to cf #2841

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
3 changes: 2 additions & 1 deletion apps/kyb-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
},
"dependencies": {
"@ballerine/blocks": "0.2.26",
"@ballerine/ui": "0.5.44",
"@ballerine/common": "^0.9.51",
"@ballerine/ui": "0.5.44",
"@ballerine/workflow-browser-sdk": "0.6.64",
"@lukemorales/query-key-factory": "^1.0.3",
"@radix-ui/react-icons": "^1.3.0",
Expand Down Expand Up @@ -48,6 +48,7 @@
"ky": "^0.33.3",
"lodash": "^4.17.21",
"lucide-react": "^0.144.0",
"motion": "^11.11.17",
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
"p-queue": "^7.4.1",
"posthog-js": "^1.154.2",
"qs": "^6.11.2",
Expand Down
29 changes: 18 additions & 11 deletions apps/kyb-app/src/common/components/layouts/Signup/Background.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FunctionComponent } from 'react';
import { motion } from 'motion/react';
import { FunctionComponent, useState } from 'react';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
import { useSignupLayout } from './hooks/useSignupLayout';

interface IBackgroundProps {
Expand All @@ -9,19 +10,25 @@ interface IBackgroundProps {
export const Background: FunctionComponent<IBackgroundProps> = props => {
const { themeParams } = useSignupLayout();
const { imageSrc, styles } = { ...props, ...themeParams?.background };
const [isLoaded, setIsLoaded] = useState(false);

if (!imageSrc) return null;

return (
<div
className="h-full min-w-[62%] flex-1"
style={{
...styles,
backgroundImage: `url(${imageSrc})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
></div>
<motion.div className="h-screen min-w-[62%] flex-1 overflow-hidden">
<motion.img
src={imageSrc}
className="h-full w-full object-cover"
style={styles}
initial={{ opacity: 0, scale: 1.2 }}
animate={isLoaded ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 1.2 }}
exit={{ opacity: 0 }}
transition={{
duration: 0.6,
ease: 'easeOut',
}}
onLoad={() => setIsLoaded(true)}
/>
</motion.div>
);
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
};
6 changes: 5 additions & 1 deletion apps/kyb-app/src/common/components/layouts/Signup/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import DOMPurify from 'dompurify';
import { motion } from 'motion/react';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
import { CSSProperties, FunctionComponent } from 'react';
import { useSignupLayout } from './hooks/useSignupLayout';

Expand All @@ -14,9 +15,12 @@ export const Footer: FunctionComponent<IFooterProps> = props => {
if (!rawHtml) return null;

return (
<div
<motion.div
className="font-inter text-base text-[#94A3B8]"
style={styles}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.6 }}
dangerouslySetInnerHTML={{ __html: DOMPurify(window).sanitize(rawHtml) }}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { motion } from 'motion/react';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
import { CSSProperties, FunctionComponent } from 'react';
import { useSignupLayout } from './hooks/useSignupLayout';

Expand All @@ -17,8 +18,14 @@ export const FormContainer: FunctionComponent<IFormContainerProps> = ({
};

return (
<div className="my-6 flex flex-col gap-4 pr-10" style={containerStyles}>
<motion.div
className="my-6 flex flex-col gap-4 pr-10"
style={containerStyles}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.5 }}
>
{children}
</div>
</motion.div>
);
};
19 changes: 17 additions & 2 deletions apps/kyb-app/src/common/components/layouts/Signup/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { motion } from 'motion/react';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
import { CSSProperties, FunctionComponent } from 'react';
import { useSignupLayout } from './hooks/useSignupLayout';

Expand All @@ -16,8 +17,22 @@ export const Header: FunctionComponent<IHeaderProps> = props => {

return (
<div className="flex flex-col gap-6 pb-6" style={containerStyles}>
<h1 className="text-2xl font-bold">{headingText}</h1>
<p className="text-base">{subheadingText}</p>
<motion.h1
className="text-2xl font-bold"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
{headingText}
</motion.h1>
<motion.p
className="text-base"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
>
{subheadingText}
</motion.p>
</div>
);
};
15 changes: 13 additions & 2 deletions apps/kyb-app/src/common/components/layouts/Signup/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CSSProperties, FunctionComponent } from 'react';
import { motion } from 'motion/react';
import { CSSProperties, FunctionComponent, useState } from 'react';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
import { useSignupLayout } from './hooks/useSignupLayout';
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved

interface ILogoProps {
Expand All @@ -9,8 +10,18 @@ interface ILogoProps {
export const Logo: FunctionComponent<ILogoProps> = props => {
const { themeParams } = useSignupLayout();
const { imageSrc, styles } = { ...props, ...themeParams?.companyLogo };
const [isLoaded, setIsLoaded] = useState(false);

if (!imageSrc) return null;

return <img src={imageSrc} style={styles} />;
return (
<motion.img
src={imageSrc}
style={styles}
initial={{ opacity: 0, scale: 0.8 }}
animate={isLoaded ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5 }}
onLoad={() => setIsLoaded(true)}
/>
);
};
17 changes: 16 additions & 1 deletion apps/kyb-app/src/common/components/layouts/Signup/Signup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ITheme } from '@/common/types/settings';
import { AnimatePresence, motion } from 'motion/react';
import { FunctionComponent } from 'react';
import { SignupLayoutProvider } from './context/SignupLayoutProvider';

Expand All @@ -10,7 +11,21 @@ interface ISignupProps {
export const Signup: FunctionComponent<ISignupProps> = ({ children, themeParams }) => {
return (
<SignupLayoutProvider themeParams={themeParams}>
<div className="flex h-full min-h-screen w-full flex-row flex-nowrap">{children}</div>
<AnimatePresence mode="wait">
<motion.div
className="flex h-full min-h-screen w-full flex-row flex-nowrap"
exit={{
opacity: 0,
transition: {
duration: 5,
ease: 'easeInOut',
},
}}
initial={{ opacity: 1 }}
>
{children}
</motion.div>
</AnimatePresence>
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
</SignupLayoutProvider>
);
};

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { InvalidAccessTokenError } from '@/common/errors/invalid-access-token';
import { useCustomerQuery } from '@/hooks/useCustomerQuery';
import { useEndUserQuery } from '@/hooks/useEndUserQuery';
import { useFlowContextQuery } from '@/hooks/useFlowContextQuery';
import { useLanguage } from '@/hooks/useLanguage';
import { useUISchemasQuery } from '@/hooks/useUISchemasQuery';
import { LoadingScreen } from '@/pages/CollectionFlow/components/atoms/LoadingScreen';
import { HTTPError } from 'ky';
import { FunctionComponent, useEffect, useMemo, useState } from 'react';
import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
import { DependenciesContext } from './dependencies-context';
import { getJsonErrors, isShouldIgnoreErrors } from './helpers';

interface IDependenciesProviderProps {
Expand All @@ -14,13 +18,19 @@ export const DependenciesProvider: FunctionComponent<IDependenciesProviderProps>
children,
}: IDependenciesProviderProps) => {
const [error, setError] = useState<Error | null>(null);
const { refetch: refetchEndUser } = useEndUserQuery();
const [isInitialLoading, setIsInitialLoading] = useState(true);

const language = useLanguage();

const dependancyQueries = [
useCustomerQuery(),
useFlowContextQuery(),
useUISchemasQuery(language),
] as const satisfies readonly [
ReturnType<typeof useCustomerQuery>,
ReturnType<typeof useFlowContextQuery>,
ReturnType<typeof useUISchemasQuery>,
];

const isLoading = useMemo(() => {
Expand All @@ -29,10 +39,22 @@ export const DependenciesProvider: FunctionComponent<IDependenciesProviderProps>
: false;
}, [dependancyQueries]);

useEffect(() => {
if (isLoading) return;

setIsInitialLoading(false);
}, [isLoading]);

const errors = useMemo(() => {
return dependancyQueries.filter(dependency => dependency.error);
}, [dependancyQueries]);

const refetchAll = useCallback(async () => {
await refetchEndUser(); // It will trigger refetch of all dependencies
}, [refetchEndUser]);

const context = useMemo(() => ({ refetchAll, isLoading }), [refetchAll, isLoading]);
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
if (!Array.isArray(errors) || !errors?.length) return;

Expand All @@ -55,13 +77,13 @@ export const DependenciesProvider: FunctionComponent<IDependenciesProviderProps>
void handleErrors(errors.map(error => error.error) as HTTPError[]);
}, [errors]);

if (isLoading) {
return <LoadingScreen />;
}

if (error) {
throw error;
}

return <>{children}</>;
if (isInitialLoading) {
return <LoadingScreen isLoading={isInitialLoading} />;
}

return <DependenciesContext.Provider value={context}>{children}</DependenciesContext.Provider>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createContext } from 'react';
import { IDependenciesContext } from './types';

export const DependenciesContext = createContext<IDependenciesContext>({
refetchAll: async () => {},
isLoading: false,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useDependencies';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { useContext } from 'react';
import { DependenciesContext } from '../../dependencies-context';

export const useDependencies = () => useContext(DependenciesContext);
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './DependenciesProvider';
export * from './hooks/useDependencies';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IDependenciesContext {
refetchAll: () => Promise<void>;
isLoading: boolean;
}
8 changes: 4 additions & 4 deletions apps/kyb-app/src/components/layouts/AppShell/AppShell.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Logo } from '@/components/layouts/AppShell/Logo';
import { Content } from '@/components/layouts/AppShell/Content';
import { Sidebar } from '@/components/layouts/AppShell/Sidebar';
import { Navigation } from '@/components/layouts/AppShell/Navigation';
import { FormContainer } from '@/components/layouts/AppShell/FormContainer';
import { LanguagePicker } from '@/components/layouts/AppShell/LanguagePicker';
import { Logo } from '@/components/layouts/AppShell/Logo';
import { Navigation } from '@/components/layouts/AppShell/Navigation';
import { Sidebar } from '@/components/layouts/AppShell/Sidebar';

interface Props {
children: React.ReactNode | React.ReactNode[];
}

export const AppShell = ({ children }: Props) => {
return <div className="w-ful flex h-screen flex-nowrap">{children}</div>;
return <div className="w-full flex h-screen flex-nowrap overflow-y-hidden">{children}</div>;
};

AppShell.FormContainer = FormContainer;
Expand Down
8 changes: 6 additions & 2 deletions apps/kyb-app/src/components/layouts/AppShell/Content.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { AnyChildren } from '@ballerine/ui';
import { motion } from 'motion/react';

interface Props {
children: AnyChildren;
}

export const Content = ({ children }: Props) => {
return (
<div
<motion.div
className="text-secondary-foreground h-full w-[100%] overflow-auto p-4"
style={{
background: 'var(--secondary)',
}}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.5 }}
>
{children}
</div>
</motion.div>
chesterkmr marked this conversation as resolved.
Show resolved Hide resolved
);
};
4 changes: 2 additions & 2 deletions apps/kyb-app/src/components/layouts/AppShell/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { useTranslation } from 'react-i18next';
import { usePageResolverContext } from '@/components/organisms/DynamicUI/PageResolver/hooks/usePageResolverContext';
import { useStateManagerContext } from '@/components/organisms/DynamicUI/StateManager/components/StateProvider';
import { useDynamicUIContext } from '@/components/organisms/DynamicUI/hooks/useDynamicUIContext';
import { useCustomer } from '@/components/providers/CustomerProvider';
import { useAppExit } from '@/hooks/useAppExit/useAppExit';
import { useCustomerQuery } from '@/hooks/useCustomerQuery';
import { ctw } from '@ballerine/ui';

export const Navigation = () => {
const { state } = useDynamicUIContext();
const { t } = useTranslation();
const { stateApi, payload } = useStateManagerContext();
const { currentPage } = usePageResolverContext();
const { customer } = useCustomer();
const { customer } = useCustomerQuery();
const { exit, isExitAvailable } = useAppExit();

const currentPageNumber =
Expand Down
Loading
Loading