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
13 changes: 13 additions & 0 deletions .changeset/dref-landing-page-feedback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"go-web-app": patch
---

Address DREF landing page feedback (LPC01-LPC25, LPF01/LPF03)

- Update DREF Procedures, DREF Guidelines and RBM resource links; Guidelines now points at the public ifrc.org document
- Hide the Advance Payment Form button until the form URL is published
- Update the Imminent DREF and EAP text box copy on the Anticipatory Pillar
- Space the Anticipatory Pillar intro paragraphs and bullet the EAP/sEAP definitions
- Add the AA Manual link to the decision tree's EAP development outcome (DREFDecisionTree_2026.08.28)
- Emphasise the leading term of each Characteristics entry, and the section titles inside the process answers
- Nest the s/EAP submission consequences under their parent step so the development process is no longer misnumbered
1 change: 1 addition & 0 deletions app/src/components/domain/DrefDecisionTree/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"drefApplicationFormButton": "DREF Application Form",
"drefGuidelinesButton": "DREF Guidelines",
"eapDevelopmentRegistrationButton": "Early Action Protocol Development Registration",
"aaManualButton": "AA Manual",
"questionEventOccurred": "Has the event already occurred?",
"questionNature": "What is the nature of the disaster?",
"questionSize": "What size of operation are you aiming at?",
Expand Down
1 change: 1 addition & 0 deletions app/src/components/domain/DrefDecisionTree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ function DrefDecisionTreeModal(props: Props) {
'cta.drefApplicationForm': strings.drefApplicationFormButton,
'cta.drefGuidelines': strings.drefGuidelinesButton,
'cta.eapDevelopmentRegistration': strings.eapDevelopmentRegistrationButton,
'cta.aaManual': strings.aaManualButton,
}),
[strings],
);
Expand Down
9 changes: 8 additions & 1 deletion app/src/components/domain/DrefDecisionTree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ONSET_SUDDEN,
} from '#utils/constants';
import {
DREF_AA_MANUAL_URL,
DREF_GUIDELINES_ADVANCE_PAYMENT_URL,
DREF_GUIDELINES_DROUGHT_URL,
DREF_GUIDELINES_EAP_ACTIVATION_URL,
Expand All @@ -26,7 +27,7 @@ import {

// DREF DECISION TREE - DREF FUNDING OPTIONS
//
// Mirrors DREFDecisionTree_2026.08.24.pdf. Flat node graph: each question's option
// Mirrors DREFDecisionTree_2026.08.28.pdf. Flat node graph: each question's option
// points (`next`) at another node id. Outcomes are shared only where BOTH the seeded
// form state and the guidance target match, which is why the two "Response DREF" and
// the two "Drought DREF" leaves are separate nodes: the slow-onset pair links to the
Expand Down Expand Up @@ -298,6 +299,12 @@ const drefDecisionTree: DecisionTree = {
labelKey: 'cta.eapDevelopmentRegistration',
},
drefGuidelines(DREF_GUIDELINES_EAP_DEVELOPMENT_URL),
// Appended, not prepended: engine.test.ts asserts actions[0] is the form.
{
type: 'external',
url: DREF_AA_MANUAL_URL,
labelKey: 'cta.aaManual',
},
],
},
},
Expand Down
31 changes: 31 additions & 0 deletions app/src/components/domain/Faq/FaqHeading/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { type ReactNode } from 'react';
import { Heading } from '@ifrc-go/ui';

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

interface Props {
children: ReactNode;
// 'section' is a top-level block inside an answer; 'subsection' sits under one.
variant: 'section' | 'subsection';
}

// Titles inside an FAQ answer. The upper-casing is applied in CSS rather than baked
// into the translated string, so translations stay free to follow their own casing
// conventions (and scripts without letter case are unaffected).
function FaqHeading(props: Props) {
const {
children,
variant,
} = props;

return (
<Heading
level={6}
className={variant === 'section' ? styles.sectionHeading : styles.subsectionHeading}
>
{children}
</Heading>
);
}

export default FaqHeading;
12 changes: 12 additions & 0 deletions app/src/components/domain/Faq/FaqHeading/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.section-heading {
text-transform: uppercase;
/* FIXME: remove force override */
font-weight: var(--go-ui-font-weight-bold)!important;
}

.subsection-heading {
text-transform: uppercase;
text-decoration: underline dotted;
/* FIXME: remove force override */
font-weight: var(--go-ui-font-weight-medium)!important;
}
40 changes: 40 additions & 0 deletions app/src/components/domain/Faq/TermText/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { type ReactNode } from 'react';
import { isDefined } from '@togglecorp/fujs';

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

interface Props {
className?: string;
// Carries its own colon, so that translations keep control of the punctuation:
// French and Spanish put a space before it.
term: string;
// The rest of the sentence. Omitted where the term stands alone, as a lead-in
// line or an inline phrase.
children?: ReactNode;
variant: 'bold' | 'underline';
}

function TermText(props: Props) {
const {
className,
term,
children,
variant,
} = props;

return (
<span className={className}>
<span className={variant === 'bold' ? styles.boldTerm : styles.underlinedTerm}>
{term}
</span>
{isDefined(children) && (
<>
{' '}
{children}
</>
)}
</span>
);
}

export default TermText;
7 changes: 7 additions & 0 deletions app/src/components/domain/Faq/TermText/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.bold-term {
font-weight: var(--go-ui-font-weight-bold);
}

.underlined-term {
text-decoration: underline dotted;
}
53 changes: 27 additions & 26 deletions app/src/components/domain/Faq/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,42 @@ import {
ListView,
} from '@ifrc-go/ui';

export interface FaqItem {
// Stable key — independent of the (translatable) question text.
name: string;
question: ReactNode;
answer: ReactNode;
}

interface Props {
className?: string;
items: FaqItem[];
// Anchor id, stable in a way the translated question is not.
name: string;
question: ReactNode;
// Siblings are spaced apart, so do not wrap the answer in a single element.
children: ReactNode;
}

function Faq(props: Props) {
const { className, items } = props;
const {
className,
name,
question,
children,
} = props;

return (
<ListView
<ExpandableContainer
className={className}
layout="block"
spacing="xs"
id={name}
heading={question}
headingLevel={5}
withHeaderBorder
withShadow
withPadding
withBackground
>
{items.map((item) => (
<ExpandableContainer
key={item.name}
heading={item.question}
headingLevel={5}
withHeaderBorder
withShadow
withPadding
withBackground
>
{item.answer}
</ExpandableContainer>
))}
</ListView>
<ListView
layout="block"
spacing="lg"
withSpacingOpticalCorrection
>
{children}
</ListView>
</ExpandableContainer>
);
}

Expand Down
28 changes: 28 additions & 0 deletions app/src/components/domain/FaqList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type ReactNode } from 'react';
import { ListView } from '@ifrc-go/ui';

interface Props {
className?: string;
children: ReactNode;
}

// Tighter spacing than the surrounding sections, so collapsed questions read as one
// block.
function FaqList(props: Props) {
const {
className,
children,
} = props;

return (
<ListView
className={className}
layout="block"
spacing="xs"
>
{children}
</ListView>
);
}

export default FaqList;
7 changes: 6 additions & 1 deletion app/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ul, ol {
}

li {
margin: var(--go-ui-spacing-2xs) 0;
margin: var(--go-ui-spacing-3xs) 0;

&:first-child {
margin-top: unset;
Expand All @@ -59,6 +59,11 @@ li {
}
}

li ul {
margin-block-start: var(--go-ui-spacing-3xs);
}


@media print {
@page {
size: portrait A4;
Expand Down
15 changes: 7 additions & 8 deletions app/src/utils/domain/dref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,16 @@ export const EMERGENCY_APPEAL_RESOURCES_URL = 'https://ifrcorg.sharepoint.com/:f
export const DREF_ANTICIPATORY_GUIDANCE_URL = `${GO_WIKI_DREF_GUIDELINES}#h-3-anticipatory-pillar`;
export const DREF_RESPONSE_GUIDANCE_URL: string | undefined = `${GO_WIKI_DREF_GUIDELINES}#h-4-response-pillar`;

// Key DREF resources. The SharePoint links are the ones supplied by the DREF team with
// their mail-session parameters (ct/or/ga/LOF/cid/ovuser/xsdata) stripped, leaving only
// the document identity. They still require an IFRC login.
export const DREF_PROCEDURES_URL: string | undefined = 'https://ifrcorg.sharepoint.com/sites/IFRCSharing/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FIFRCSharing%2FShared%20Documents%2FDREF%2FNew%20DREF%20Procedures%2FDREF%20Procedures%5Fsigned%2Dversion%2Epdf&parent=%2Fsites%2FIFRCSharing%2FShared%20Documents%2FDREF%2FNew%20DREF%20Procedures';
export const DREF_GUIDELINES_URL: string | undefined = 'https://ifrcorg.sharepoint.com/sites/IFRCSharing/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FIFRCSharing%2FShared%20Documents%2FDREF%2FDREF%20Procedures%20and%20Guidelines%2FDREF%20Guidelines%202026%2Epdf&parent=%2Fsites%2FIFRCSharing%2FShared%20Documents%2FDREF%2FDREF%20Procedures%20and%20Guidelines';
export const DREF_RBM_URL: string | undefined = 'https://ifrcorg.sharepoint.com/:f:/s/IFRCSharing/IgBYYWWQVGHiS5rnwYXIX1ObAYFM5-IBl4BLsh_vSKwQwAE';
// Key DREF resources, as confirmed by the DREF team (LPC08/LPF03/LPC24). Procedures and
// RBM are SharePoint share links and require an IFRC login; Guidelines is public.
export const DREF_PROCEDURES_URL: string | undefined = 'https://ifrcorg.sharepoint.com/:b:/s/IFRCSharing/IQDwmkZKcxsNSrW_CatNVmKpAfd5uNDDdu4enwzYRMBE8tI?e=iwjy9g';
export const DREF_GUIDELINES_URL: string | undefined = 'https://www.ifrc.org/document/dref-guidelines-2026';
export const DREF_RBM_URL: string | undefined = 'https://ifrcorg.sharepoint.com/:b:/s/IFRCSharing/IQCmkADgBvdhTaBt6aJJznDnAbB1MoUG-R4PSkprVaYD_K0?e=lgCz1W';
export const ANTICIPATION_HUB_URL: string | undefined = 'https://www.anticipation-hub.org/';
export const DREF_ERF_URL: string | undefined = 'https://www.ifrc.org/sites/default/files/2026-04/IFRC%20Emergency%20Response%20Framework.pdf';

// TODO: fill in once the form is published; until then DrefDocumentLink renders a
// disabled button.
// TODO: fill in once the form is published. Until then the Advance Payment Form button
// is hidden entirely (LPC25), not rendered disabled.
export const DREF_ADVANCE_PAYMENT_FORM_URL: string | undefined = undefined;

// Router state consumed by DrefApplicationForm (via useLocation().state) to seed a
Expand Down
Loading
Loading