Skip to content
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
1 change: 0 additions & 1 deletion app/src/App/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,6 @@ const simplifiedEapExport = customWrapRoute({
},
});


type DefaultPerProcessChild = 'new';
const perProcessLayout = customWrapRoute({
parent: rootLayout,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useCallback } from 'react';
import {
type CheckboxProps,
InputError,
} from '@ifrc-go/ui';
import { _cs } from '@togglecorp/fujs';

import styles from './styles.module.css';

function TimeSpanCheck<const NAME>(props: CheckboxProps<NAME>) {
const {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
checkmarkClassName,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
checkmarkContainerClassName,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
inputClassName,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
labelContainerClassName,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
description,

className: classNameFromProps,
disabled,
error,
indeterminate,
invertedLogic = false,
label,
name,
onChange,
readOnly,
tooltip,
value,
withBackground,
withDarkBackground,
...otherProps
} = props;

const handleChange = useCallback(
(e: React.FormEvent<HTMLInputElement>) => {
const v = e.currentTarget.checked;
onChange(
invertedLogic ? !v : v,
name,
);
},
[name, onChange, invertedLogic],
);

const checked = invertedLogic ? !value : value;

const className = _cs(
styles.checkbox,
classNameFromProps,
!indeterminate && checked && styles.checked,
withBackground && styles.withBackground,
withDarkBackground && styles.withDarkBackground,
disabled && styles.disabledCheckbox,
readOnly && styles.readOnly,
);

return (
<label // eslint-disable-line jsx-a11y/label-has-associated-control
className={_cs(
styles.timeSpanCheck,
value && styles.checked,
className,
)}
title={tooltip}
>
<input
onChange={handleChange}
className={styles.input}
type="checkbox"
checked={checked ?? false}
disabled={disabled || readOnly}
readOnly={readOnly}
{...otherProps} // eslint-disable-line react/jsx-props-no-spreading
/>
{label}
{error && (
<InputError floating>
{error}
</InputError>
)}
</label>
);
}

export default TimeSpanCheck;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.time-span-check {
display: flex;
align-items: center;
justify-content: center;
border: var(--go-ui-width-separator-thin) solid var(--go-ui-color-gray-50);
border-radius: var(--go-ui-border-radius-md);
cursor: pointer;
padding: 0 var(--go-ui-spacing-3xs);
min-width: 1.5rem;
height: 1.5rem;
text-align: center;
font-size: var(--go-ui-font-size-sm);

&.checked {
border-color: var(--go-ui-color-primary-red);
background-color: var(--go-ui-color-primary-red);
color: var(--go-ui-color-text-on-dark);
}

.input {
position: absolute;
opacity: 0;
margin: 0;
padding: 0;
width: 0;
height: 0;
pointer-events: none;
}
}
8 changes: 8 additions & 0 deletions app/src/components/domain/OperationActivityInput/i18n.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"namespace": "operationActivityInput",
"strings": {
"operationPriorityActionLabel": "Priority action",
"operationTimeFrameLabel": "Time Frame",
"operationTimeValueLabel": "Time Value"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DeleteBinTwoLineIcon } from '@ifrc-go/icons';
import {
Button,
Checklist,
Container,
InlineLayout,
ListView,
SelectInput,
TextInput,
Expand All @@ -17,23 +17,20 @@ import {
useFormObject,
} from '@togglecorp/toggle-form';

import { type components } from '#generated/types';
import useGlobalEnums from '#hooks/domain/useGlobalEnums';
import { type GoApiResponse } from '#utils/restRequest';

import { type PartialSimplifiedEapType } from '../../../schema';
import { type OperationActivityFormFields } from './schema';
import TimeSpanCheck from './TimeSpanCheck';

import i18n from './i18n.json';

type ApproachesFormFields = NonNullable<PartialSimplifiedEapType['enable_approaches']>[number];
type ActivityFormField = NonNullable<ApproachesFormFields['early_action_activities']>[number];

type GlobalEnumsResponse = GoApiResponse<'/api/v2/global-enums/'>;
type TimeframeOption = NonNullable<GlobalEnumsResponse['eap_timeframe']>[number];

const defaultActivityValue: ActivityFormField = {
const defaultActivityValue: OperationActivityFormFields = {
client_id: '-1',
};

type TimeframeOption = components['schemas']['EapTimeframeEnum'];

function timeframeKeySelector(option: TimeframeOption) {
return option.key;
}
Expand All @@ -43,15 +40,15 @@ const timeValueKeySelector = (
) => option.key;

interface Props {
value: ActivityFormField;
error: ArrayError<ActivityFormField> | undefined;
onChange: (value: SetValueArg<ActivityFormField>, index: number) => void;
value: OperationActivityFormFields;
error: ArrayError<OperationActivityFormFields> | undefined;
onChange: (value: SetValueArg<OperationActivityFormFields>, index: number) => void;
onRemove: (index: number) => void;
index: number;
disabled?: boolean;
}

function ActivityInput(props: Props) {
function OperationActivityInput(props: Props) {
const {
error: errorFromProps,
onChange,
Expand Down Expand Up @@ -110,31 +107,31 @@ function ActivityInput(props: Props) {
);

return (
<Container
headerActions={(
<InlineLayout
after={(
<Button
name={index}
onClick={onRemove}
styleVariant="outline"
styleVariant="action"
title="Remove"
disabled={disabled}
>
<DeleteBinTwoLineIcon />
</Button>
)}
>
<ListView layout="block">
<ListView layout="grid" numPreferredGridColumns={3}>
<TextInput
label={strings.approachReadiness}
name="activity"
value={value.activity}
onChange={onFieldChange}
disabled={disabled}
withAsterisk
/>
<ListView layout="grid">
<TextInput
label={strings.operationPriorityActionLabel}
name="activity"
value={value.activity}
onChange={onFieldChange}
disabled={disabled}
withAsterisk
/>
<ListView layout="grid">
<SelectInput
label={strings.approachTimeFrame}
label={strings.operationTimeFrameLabel}
name="timeframe"
value={value.timeframe}
onChange={handleTimeframeChange}
Expand All @@ -144,23 +141,25 @@ function ActivityInput(props: Props) {
disabled={disabled}
error={error?.timeframe}
/>

{value?.timeframe && (
<Checklist
label={strings.approachTimeValue}
label={strings.operationTimeValueLabel}
name="time_value"
value={value?.time_value}
spacing="xs"
onChange={onFieldChange}
keySelector={timeValueKeySelector}
labelSelector={stringValueSelector}
options={timeValueOptions}
disabled={disabled}
renderer={TimeSpanCheck}
withoutOpticalSpacingCorrection
/>
)}
</ListView>
</ListView>
</Container>
</InlineLayout>
);
}

export default ActivityInput;
export default OperationActivityInput;
27 changes: 27 additions & 0 deletions app/src/components/domain/OperationActivityInput/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
type ObjectSchema,
type PartialForm,
undefinedValue,
} from '@togglecorp/toggle-form';

import { type components } from '#generated/types';

type OperationActivity = components['schemas']['OperationActivity'];

export type OperationActivityFormFields = PartialForm<Omit<OperationActivity, 'timeframe_display'>> & {
client_id: string;
}

type OperationActivitySchema = ObjectSchema<OperationActivityFormFields>;

const schema: OperationActivitySchema = {
fields: (): ReturnType<OperationActivitySchema['fields']> => ({
client_id: {},
id: { defaultValue: undefinedValue },
activity: {},
time_value: {},
timeframe: {},
}),
};

export default schema;
Empty file.
Empty file.
Empty file.
Empty file.
7 changes: 5 additions & 2 deletions app/src/views/AccountMyFormsEap/EapTableActions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { TableActions } from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import { isNotDefined } from '@togglecorp/fujs';

import DropdownMenuItem from '#components/DropdownMenuItem';
import Link from '#components/Link';
import {
EAP_TYPE_FULL,
EAP_TYPE_SIMPLIFIED,
} from '#utils/constants';
import { type GoApiResponse } from '#utils/restRequest';

import i18n from './i18n.json';
import { isNotDefined } from '@togglecorp/fujs';
import { EAP_TYPE_FULL, EAP_TYPE_SIMPLIFIED } from '#utils/constants';

type EapResponse = GoApiResponse<'/api/v2/eap-registration/{id}/'>;

Expand Down
2 changes: 1 addition & 1 deletion app/src/views/SimplifiedEapExport/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"prioritizedHazardAndImpactHeading": "Prioritized hazard and its historical impact",
"riskSelectedProtocolsHeading": "Explain which risks have been selected for this protocol and why",
"earlyActionInterventionHeading": "Early Action Intervention",
"overallObjectiveInterventionHeading": "Overall objective of the invervention",
"overallObjectiveInterventionHeading": "Overall objective of the intervention",
"potentialGeographicalHighRiskAreasHeading": "Potential geographical high-risk areas that the simplified EAP would target",
"assistedThroughOperationHeading": "Who will be assisted through this operation and what criteria will be used for their selection?",
"triggerStatementHeading": "Trigger(s) statement",
Expand Down
Loading
Loading