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

Phases Design #34

Merged
merged 7 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions apps/widget/src/components/Common/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Group } from '@mantine/core';
import { Button } from '@ui/Button';
import { TEXTS } from '@config';

interface IFooterProps {
active: number;
onPrevClick: () => void;
onNextClick: () => void;
}

export function Footer(props: IFooterProps) {
const { active, onNextClick, onPrevClick } = props;

return (
<Group spacing="md" style={{ alignSelf: 'flex-end' }}>
{active === 1 ? (
<Button onClick={onNextClick}>{TEXTS.PHASE1.SEE_MAPPING}</Button>
) : active === 2 ? (
<>
<Button onClick={onPrevClick} variant="outline">
{TEXTS.PHASE2.UPLOAD_AGAIN}
</Button>
<Button onClick={onNextClick}>{TEXTS.PHASE2.SEE_REVIEW}</Button>
</>
) : active === 3 ? (
<>
<Button onClick={onPrevClick} variant="outline">
{TEXTS.PHASE3.BACK_TO_MAPPING}
</Button>
<Button onClick={onNextClick}>{TEXTS.PHASE3.CONFIRM_UPLOAD}</Button>
</>
) : active === 4 ? (
<Button onClick={onNextClick}>{TEXTS.COMPLETE.UPLOAD_AGAIN}</Button>
) : null}
</Group>
);
}
1 change: 1 addition & 0 deletions apps/widget/src/components/Common/Footer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Footer';
40 changes: 40 additions & 0 deletions apps/widget/src/components/Common/Heading/Heading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Group, Title } from '@mantine/core';
import { Stepper } from '@ui/Stepper';
import { TEXTS } from '@config';

interface IHeadingProps {
active: number;
}

const Titles = {
1: TEXTS.TITLES.UPLOAD,
2: TEXTS.TITLES.MAPPING,
3: TEXTS.TITLES.REVIEW,
4: TEXTS.TITLES.COMPLETE,
};

const Steps = [
{
label: TEXTS.STEPS.UPLOAD,
},
{
label: TEXTS.STEPS.MAPPING,
},
{
label: TEXTS.STEPS.REVIEW,
},
{
label: TEXTS.STEPS.COMPLETE,
},
];

export function Heading(props: IHeadingProps) {
const { active } = props;

return (
<Group style={{ justifyContent: 'space-between' }} mb="lg">
<Title order={3}>{Titles[active]}</Title>
<Stepper active={active} steps={Steps} />
</Group>
);
}
1 change: 1 addition & 0 deletions apps/widget/src/components/Common/Heading/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Heading';
28 changes: 28 additions & 0 deletions apps/widget/src/components/Common/Wrapper/Styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */
import { createStyles, MantineTheme } from '@mantine/core';

export const getRootStyles = (theme: MantineTheme): React.CSSProperties => ({
paddingRight: 24,
paddingLeft: 24,
paddingBottom: 24,
border: '1px solid transparent',
display: 'flex',
flexDirection: 'column',
height: '100%',
});

export const getContainerStyles = (theme: MantineTheme): React.CSSProperties => ({
flexDirection: 'column',
width: '100%',
alignItems: 'unset',
flexGrow: 1,
display: 'flex',
gap: theme.spacing.md,
});

export default createStyles((theme: MantineTheme, params, getRef): Record<string, any> => {
return {
root: getRootStyles(theme),
container: getContainerStyles(theme),
};
});
20 changes: 20 additions & 0 deletions apps/widget/src/components/Common/Wrapper/Wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PropsWithChildren } from 'react';
import { Heading } from 'components/Common/Heading';
import useStyles from './Styles';

interface IWrapperProps {
active: number;
}

export function Wrapper(props: PropsWithChildren<IWrapperProps>) {
const { classes } = useStyles();
const { children, active } = props;

return (
<div className={classes.root}>
{/* Heading */}
<Heading active={active} />
<div className={classes.container}>{children}</div>
</div>
);
}
1 change: 1 addition & 0 deletions apps/widget/src/components/Common/Wrapper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Wrapper';
22 changes: 21 additions & 1 deletion apps/widget/src/components/widget/Container/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as WebFont from 'webfontloader';
import { useParams } from 'react-router-dom';
import { IUserDataPayload } from '@impler/shared';
import { Global } from '@emotion/react';
import { API_URL } from '@config';
import { API_URL, colors } from '@config';
import { Provider } from '../Provider';

export function Container({ children }: PropsWithChildren) {
Expand Down Expand Up @@ -55,11 +55,31 @@ export function Container({ children }: PropsWithChildren) {
<>
<Global
styles={{
body: {
backgroundColor: 'transparent',
},
'*': {
boxSizing: 'border-box',
margin: 0,
padding: 0,
},
/* width */
'::-webkit-scrollbar': {
width: '7px',
height: '7px',
},

/* Track */
'::-webkit-scrollbar-track': {
boxShadow: 'inset 0 0 3px grey',
borderRadius: '10px',
},

/* Handle */
'::-webkit-scrollbar-thumb': {
background: colors.primary,
borderRadius: '10px',
},
}}
/>
{frameInitialized ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Warning } from '@icons';
import { colors, TEXTS } from '@config';
import { Button } from '@ui/Button';
import { Group, Modal as MantineModal, Text, Title } from '@mantine/core';

interface IConfirmModalProps {
opened: boolean;
wrongDataCount: number;
onClose: () => void;
onConfirm: (exempt: boolean) => void;
}

export function ConfirmModal(props: IConfirmModalProps) {
const { opened, onClose, wrongDataCount, onConfirm } = props;

return (
<MantineModal centered opened={opened} onClose={onClose} withCloseButton={false} padding="xl" size="lg">
<Group spacing={0} style={{ flexDirection: 'column', textAlign: 'center' }}>
<Warning fill={colors.red} styles={{ width: 40, height: 40 }} />
<Title color={colors.red} order={3} mt="sm">
{wrongDataCount}&nbsp;{TEXTS.CONFIRM_MODAL.title}
</Title>
<Text color="dimmed" mb="sm">
{TEXTS.CONFIRM_MODAL.subTitle}
</Text>
<Group spacing="sm" style={{ flexDirection: 'row' }}>
<Button onClick={() => onConfirm(true)} variant="outline">
{TEXTS.CONFIRM_MODAL.EXEMPT_CONTINUE}
</Button>
<Button onClick={() => onConfirm(false)}>{TEXTS.CONFIRM_MODAL.KEEP_CONTINUE}</Button>
</Group>
</Group>
</MantineModal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ConfirmModal';
47 changes: 47 additions & 0 deletions apps/widget/src/components/widget/Phases/Phase1/Phase1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useState } from 'react';
import { TEXTS } from '@config';
import { Select } from '@ui/Select';
import { Button } from '@ui/Button';
import { Dropzone } from '@ui/Dropzone';
import { Group } from '@mantine/core';
import { Download } from '@icons';
import useStyles from './Styles';
import { Footer } from 'components/Common/Footer';

interface IPhase1Props {
onNextClick: () => void;
}

export function Phase1(props: IPhase1Props) {
const { classes } = useStyles();
const { onNextClick } = props;
const [selectedFile, setSelectedFile] = useState<File>();

return (
<>
<Group className={classes.templateContainer} spacing="lg" noWrap>
<Select
title={TEXTS.PHASE1.SELECT_TITLE}
placeholder={TEXTS.PHASE1.SELECT_PLACEHOLDER}
data={[{ value: 'Users', label: 'Users' }]}
width="50%"
/>
<div className={classes.download}>
<Button size="sm" leftIcon={<Download />}>
{TEXTS.PHASE1.DOWNLOAD_SAMPLE}
</Button>
</div>
</Group>

<Dropzone
className={classes.dropzone}
onDrop={(file) => setSelectedFile(file[0])}
onClear={() => setSelectedFile(undefined)}
title={TEXTS.PHASE1.SELECT_FILE}
file={selectedFile}
/>

<Footer onNextClick={onNextClick} onPrevClick={() => {}} active={1} />
</>
);
}
38 changes: 38 additions & 0 deletions apps/widget/src/components/widget/Phases/Phase1/Styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */
import { createStyles, MantineTheme } from '@mantine/core';
import { colors } from '@config';

export const getContainerStyles = (theme: MantineTheme): React.CSSProperties => ({
flexDirection: 'column',
width: '100%',
alignItems: 'unset',
});

export const getTemplateContainerStyles = (theme: MantineTheme): React.CSSProperties => ({
justifyContent: 'space-between',
alignItems: 'flex-end',
width: '100%',
});

export const getDownloadTemplateStyles = (theme: MantineTheme): React.CSSProperties => ({
width: '50%',
});

export const getFooterStyles = (theme: MantineTheme): React.CSSProperties => ({
alignSelf: 'flex-end',
});

export const getDropzoneStyles = (theme: MantineTheme): React.CSSProperties => ({
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
});

export default createStyles((theme: MantineTheme, params, getRef): Record<string, any> => {
return {
container: getContainerStyles(theme),
templateContainer: getTemplateContainerStyles(theme),
download: getDownloadTemplateStyles(theme),
dropzone: getDropzoneStyles(theme),
};
});
1 change: 1 addition & 0 deletions apps/widget/src/components/widget/Phases/Phase1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Phase1';
67 changes: 67 additions & 0 deletions apps/widget/src/components/widget/Phases/Phase2/Phase2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Group, Text } from '@mantine/core';
import { MappingItem } from '@ui/MappingItem';
import { TEXTS } from '@config';
import { Footer } from 'components/Common/Footer';
import useStyles from './Styles';
import { useEffect, useRef, useState } from 'react';

interface IPhase2Props {
onPrevClick: () => void;
onNextClick: () => void;
}

export function Phase2(props: IPhase2Props) {
const wrapperRef = useRef<HTMLDivElement>() as React.MutableRefObject<HTMLDivElement>;
const titlesRef = useRef<HTMLDivElement>() as React.MutableRefObject<HTMLDivElement>;
const [wrapperHeight, setWrapperHeight] = useState(200);
const { classes } = useStyles();
const { onPrevClick, onNextClick } = props;
const options = [
{
label: 'Firstname',
value: '1',
},
{
label: 'Lastname',
value: '2',
},
];

useEffect(() => {
// setting wrapper height
setWrapperHeight(
wrapperRef.current.getBoundingClientRect().height - titlesRef.current.getBoundingClientRect().height
);
}, []);

return (
<>
<div style={{ flexGrow: 1 }} ref={wrapperRef}>
{/* Heading */}
<Group style={{ justifyContent: 'space-between' }} noWrap ref={titlesRef}>
<Group className={classes.textWrapper} align="stretch" noWrap>
<Text color="dimmed" style={{ width: '50%' }}>
{TEXTS.PHASE2.NAME_IN_SCHEMA_TITLE}
</Text>
<Text color="dimmed" style={{ width: '50%' }}>
{TEXTS.PHASE2.NAME_IN_SHEET_TITLE}
</Text>
</Group>
</Group>
{/* Mapping Items */}
<div
className={classes.mappingWrapper}
style={{
height: wrapperHeight,
}}
>
{Array.from({ length: 10 }).map((value, index) => (
<MappingItem key={index} options={options} heading="First Name" />
))}
</div>
</div>

<Footer active={2} onNextClick={onNextClick} onPrevClick={onPrevClick} />
</>
);
}
26 changes: 26 additions & 0 deletions apps/widget/src/components/widget/Phases/Phase2/Styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */
import { createStyles, MantineTheme } from '@mantine/core';

export const getTextWrapperStyles = (theme: MantineTheme): React.CSSProperties => ({
[`@media (max-width: ${theme.breakpoints.md}px)`]: {
width: '100%',
},
[`@media (min-width: ${theme.breakpoints.md}px)`]: {
width: '70%',
},
});

export const getMappingWrapperStyles = (theme: MantineTheme): React.CSSProperties => ({
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
gap: '15px',
paddingRight: 5,
});

export default createStyles((theme: MantineTheme, params, getRef): Record<string, any> => {
return {
textWrapper: getTextWrapperStyles(theme),
mappingWrapper: getMappingWrapperStyles(theme),
};
});
1 change: 1 addition & 0 deletions apps/widget/src/components/widget/Phases/Phase2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Phase2';
Loading