Skip to content

Commit f2e555c

Browse files
committed
feat(eap): add export for simplified EAP
1 parent 024634c commit f2e555c

22 files changed

Lines changed: 984 additions & 12 deletions

File tree

app/src/App/routes/index.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,21 @@ const eapDevelopmentRegistrationForm = customWrapRoute({
12261226
},
12271227
});
12281228

1229+
const simplifiedEapExport = customWrapRoute({
1230+
parent: rootLayout,
1231+
path: 'eap/:eapId/export',
1232+
component: {
1233+
render: () => import('#views/SimplifiedEapExport'),
1234+
props: {},
1235+
},
1236+
wrapperComponent: Auth,
1237+
context: {
1238+
title: 'Simplified EAP Export',
1239+
visibility: 'is-authenticated',
1240+
},
1241+
});
1242+
1243+
12291244
type DefaultPerProcessChild = 'new';
12301245
const perProcessLayout = customWrapRoute({
12311246
parent: rootLayout,
@@ -1504,6 +1519,7 @@ const wrappedRoutes = {
15041519
drefProcessLayout,
15051520
eapRegistrationLayout,
15061521
eapDevelopmentRegistrationForm,
1522+
simplifiedEapExport,
15071523
};
15081524

15091525
export const unwrappedRoutes = unwrapRoute(Object.values(wrappedRoutes));
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
Heading,
3+
type HeadingProps,
4+
} from '@ifrc-go/ui/printable';
5+
import { getSpacingValue } from '@ifrc-go/ui/utils';
6+
7+
import styles from './styles.module.css';
8+
9+
interface Props {
10+
heading?: React.ReactNode;
11+
headingLevel?: HeadingProps['level'];
12+
breakBefore?: boolean;
13+
breakAfter?: boolean;
14+
children?: React.ReactNode;
15+
}
16+
17+
function PrintableContainer(props: Props) {
18+
const {
19+
heading,
20+
headingLevel = 3,
21+
breakAfter,
22+
breakBefore,
23+
children,
24+
} = props;
25+
26+
const spacing = getSpacingValue('3xl', -headingLevel);
27+
28+
return (
29+
<>
30+
{breakBefore && <div className={styles.pageBreak} />}
31+
{heading && (
32+
<Heading level={headingLevel}>
33+
{heading}
34+
</Heading>
35+
)}
36+
{children}
37+
<div style={{ marginBlockEnd: spacing }} />
38+
{breakAfter && <div className={styles.pageBreak} />}
39+
</>
40+
);
41+
}
42+
43+
export default PrintableContainer;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.page-break {
2+
break-before: page;
3+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { useMemo } from 'react';
2+
import {
3+
BooleanOutput,
4+
type BooleanOutputProps,
5+
DateOutput,
6+
type DateOutputProps,
7+
NumberOutput,
8+
type NumberOutputProps,
9+
} from '@ifrc-go/ui';
10+
import { useSpacingToken } from '@ifrc-go/ui/hooks';
11+
import {
12+
DEFAULT_INVALID_TEXT,
13+
DEFAULT_PRINT_DATE_FORMAT,
14+
fullSpacings,
15+
gapSpacings,
16+
paddingSpacings,
17+
type SpacingType,
18+
} from '@ifrc-go/ui/utils';
19+
import { _cs } from '@togglecorp/fujs';
20+
21+
import styles from './styles.module.css';
22+
23+
interface BaseProps {
24+
className?: string;
25+
label?: React.ReactNode;
26+
strongValue?: boolean;
27+
strongLabel?: boolean;
28+
withoutLabelColon?: boolean;
29+
invalidText?: React.ReactNode;
30+
variant?: 'block' | 'inline' | 'contents';
31+
withPadding?: boolean;
32+
withBackground?: boolean;
33+
spacing?: SpacingType;
34+
}
35+
36+
interface BooleanProps extends BooleanOutputProps {
37+
valueType: 'boolean',
38+
}
39+
40+
interface NumberProps extends NumberOutputProps {
41+
valueType: 'number',
42+
}
43+
44+
interface DateProps extends DateOutputProps {
45+
valueType: 'date',
46+
}
47+
48+
interface TextProps {
49+
valueType: 'text',
50+
value: string | null | undefined;
51+
}
52+
53+
interface NodeProps {
54+
valueType?: never;
55+
value?: React.ReactNode;
56+
}
57+
58+
export type Props = BaseProps & (
59+
NodeProps | TextProps | DateProps | NumberProps | BooleanProps
60+
);
61+
62+
function PrintableDataDisplay(props: Props) {
63+
const {
64+
className,
65+
label,
66+
strongLabel,
67+
strongValue,
68+
withoutLabelColon,
69+
invalidText = DEFAULT_INVALID_TEXT,
70+
variant = 'inline',
71+
withPadding,
72+
withBackground,
73+
spacing,
74+
...otherProps
75+
} = props;
76+
77+
const valueComponent = useMemo(() => {
78+
if (otherProps.valueType === 'number') {
79+
return (
80+
<NumberOutput
81+
// eslint-disable-next-line react/jsx-props-no-spreading
82+
{...otherProps}
83+
invalidText={invalidText}
84+
/>
85+
);
86+
}
87+
88+
if (otherProps.valueType === 'date') {
89+
return (
90+
<DateOutput
91+
// eslint-disable-next-line react/jsx-props-no-spreading
92+
{...otherProps}
93+
invalidText={invalidText}
94+
format={DEFAULT_PRINT_DATE_FORMAT}
95+
/>
96+
);
97+
}
98+
99+
if (otherProps.valueType === 'boolean') {
100+
return (
101+
<BooleanOutput
102+
// eslint-disable-next-line react/jsx-props-no-spreading
103+
{...otherProps}
104+
invalidText={invalidText}
105+
/>
106+
);
107+
}
108+
109+
if (!(otherProps.value instanceof Date)) {
110+
return otherProps.value || invalidText;
111+
}
112+
113+
return invalidText;
114+
}, [otherProps, invalidText]);
115+
116+
const spacingClassName = useSpacingToken({
117+
spacing,
118+
offset: -3,
119+
modes: withPadding ? fullSpacings : gapSpacings,
120+
});
121+
122+
const innerPaddingClassName = useSpacingToken({
123+
spacing,
124+
offset: -3,
125+
modes: paddingSpacings,
126+
});
127+
128+
return (
129+
<div
130+
className={_cs(
131+
styles.printableDataDisplay,
132+
variant === 'inline' && styles.inlineVariant,
133+
variant === 'block' && styles.blockVariant,
134+
variant === 'contents' && styles.contentsVariant,
135+
withBackground && styles.withBackground,
136+
spacingClassName,
137+
className,
138+
)}
139+
>
140+
<div
141+
className={_cs(
142+
styles.label,
143+
strongLabel && styles.strong,
144+
variant === 'contents' && withPadding && innerPaddingClassName,
145+
!withoutLabelColon && styles.withColon,
146+
)}
147+
>
148+
{label}
149+
</div>
150+
<div
151+
className={_cs(
152+
styles.value,
153+
strongValue && styles.strong,
154+
variant === 'contents' && withPadding && innerPaddingClassName,
155+
otherProps.valueType === 'text' && styles.textType,
156+
)}
157+
>
158+
{valueComponent}
159+
</div>
160+
</div>
161+
);
162+
}
163+
164+
export default PrintableDataDisplay;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.printable-data-display {
2+
&.inline-variant {
3+
display: flex;
4+
flex-direction: row;
5+
}
6+
7+
&.block-variant {
8+
display: flex;
9+
flex-direction: column;
10+
}
11+
12+
&.contents-variant {
13+
display: contents;
14+
}
15+
16+
&.with-background {
17+
background-color: var(--go-ui-color-background);
18+
19+
&.contents-variant {
20+
.value,
21+
.label {
22+
background-color: var(--go-ui-color-background);
23+
}
24+
}
25+
}
26+
27+
.label {
28+
&.with-colon::after {
29+
content: ':';
30+
}
31+
}
32+
33+
.value {
34+
&.text-type {
35+
text-align: justify;
36+
white-space: pre-wrap;
37+
}
38+
}
39+
40+
.strong {
41+
color: var(--go-ui-color-black);
42+
font-weight: var(--go-ui-font-weight-semibold);
43+
}
44+
}

app/src/components/printable/PrintableDescription/index.tsx

Whitespace-only changes.

app/src/components/printable/PrintableDescription/styles.module.css

Whitespace-only changes.

app/src/components/printable/PrintableLabel/index.tsx

Whitespace-only changes.

app/src/components/printable/PrintableLabel/styles.module.css

Whitespace-only changes.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import { Heading } from '@ifrc-go/ui/printable';
3+
import { _cs } from '@togglecorp/fujs';
4+
5+
import ifrcLogo from '#assets/icons/ifrc-square.png';
6+
7+
import styles from './styles.module.css';
8+
9+
interface Props {
10+
className?: string;
11+
children: React.ReactNode;
12+
heading: React.ReactNode;
13+
description: React.ReactNode;
14+
}
15+
16+
function PrintablePage(props: Props) {
17+
const {
18+
className,
19+
children,
20+
heading,
21+
description,
22+
} = props;
23+
24+
return (
25+
<main className={_cs(styles.printablePage, className)}>
26+
<div className={styles.headerSection}>
27+
<img
28+
className={styles.ifrcLogo}
29+
src={ifrcLogo}
30+
alt="IFRC"
31+
/>
32+
<Heading
33+
level={1}
34+
className={styles.heading}
35+
>
36+
{heading}
37+
</Heading>
38+
<div className={styles.description}>
39+
{description}
40+
</div>
41+
</div>
42+
{children}
43+
</main>
44+
);
45+
}
46+
47+
export default PrintablePage;

0 commit comments

Comments
 (0)