d0e0e27035
## Summary Replaces the single-screen partner-application modal with a **4-step wizard** on the public form, and points the route's upstream at the new `submit-partner-application` HTTP logic function in the twenty-partners SDK app. After design review, the Expertise step landed on the validated **Category + Skills** model: a small set of *stable* macro categories the partner operates in, plus a *free, semi-structured* Skills field for the concrete things that differentiate them (React, SAP, Shopify, …). Companion PR (partners-app side): #21040 ## ⚠️ Deployment notes Before this can ship to prod, the website worker needs a new env var: - **Add `PARTNER_APPLICATION_SECRET`** to the deploy config at https://github.com/twentyhq/twenty-infra/tree/main/cloudflare/website. Without it the route returns `503` ("Partner application endpoint is not configured."). - The value must **match** the `PARTNER_APPLICATION_SECRET` workspace variable set in the partners workspace UI (Settings → Apps → Twenty Partners → Variables) — that's how the handler authenticates the incoming `X-Application-Secret` header. - `PARTNER_APPLICATION_WEBHOOK_URL` also needs repointing from the TFT webhook to the logic-function URL (`https://partner.twenty.com/s/partner-applications` or equivalent) at the same time. ## Wizard - 4 steps inside `Modal.Root`: **Identity → Profile → Expertise → Commercials**. Step-dot indicator, per-step required-field gating, reset on close. The big serif hero shows **only on step 1**; later steps use the compact `STEP n OF 4 · NAME` strip to reclaim vertical space. - **Profile** captures Type of team (Solo/Agency), LinkedIn, City, Country, Languages. Country uses the searchable Select (placeholder-only label). - **Expertise = Category + Skills + Notes:** - **Category** — multi-select cards over 5 macro categories (`ADVISORY`, `SOLUTIONING`, `DEVELOPMENT`, `HOSTING`, `SUPPORT`), each with a one-line description + examples. (Replaces the old draft `partnerScope` enum; the backend keeps the field name — see #21040.) - **Skills** — free tag input with a clickable suggestion row + keyboard autocomplete (↑/↓/Enter/Esc) and "add your own". Empty by default. - **Notes** — one free textarea (merges the former `workspaceUrl` + `customerReferences`), reviewed manually. - `deploymentExpertise` removed from the form (covered by the Hosting category). - **In-modal success view** on submit ("Thanks, / we'll be in touch!") with a Close button — replaces the old silent close. - Removes the partners-page "Which partner program is right for you?" three-cards section. ## Design-system primitives - **`Form.Select`** — searchable popup whose dropdown is **portaled to `<body>`** (fixed, anchored to the trigger, flips up, height-capped) so the modal's `overflow`/`transform` can't clip it; pointer events are stopped so clicking inside it doesn't dismiss the dialog. - **`Form.TagInput`** — optional `suggestions` prop adds the suggestion row + autocomplete menu (used by Skills); behaviour unchanged when no suggestions are passed. - **`CategoryCardSelect`** — compact multi-select cards. - `Form.MultiSelect`, `Form.Currency`. ## Validation & payload - **Single validation source:** client and server share Zod field schemas (`partner-application-field-schemas.ts`). The reducer validates via those instead of hand-rolled regexes, so client and server agree by construction (e.g. both reject non-TLD URLs). - **Typed request body:** `buildPartnerApplicationRequestBody(state)` returns a typed `PartnerApplicationRequest` (unit-tested); `handleSubmit` just serializes it. - Payload is camelCase matching the logic-function input; `applicationNotes` replaces `workspaceUrl`/`customerReferences`. - Auth: the upstream call carries an `X-Application-Secret` header backed by `PARTNER_APPLICATION_SECRET` (handler-enforced — the SDK's `isAuthRequired` only accepts user-session JWTs, not workspace API keys). The webhook-URL env uses `z.url()` (not `z.httpUrl()`) so `http://localhost:2020/...` dev destinations parse. ## Demo 📹 _Screen recording of the wizard end-to-end (open → walk steps → submit → Partner record lands):_ https://github.com/user-attachments/assets/7458dd86-e3ff-47b5-9878-0eb134ff38e3 ## Tests - **62 passing** across reducer, Zod schema, route, the new payload-builder suite, and Form helper suites. `npx tsc` clean, `nx lint:diff-with-main` clean, Lingui catalogs regenerated (French slots are a follow-up). ## Test plan - [ ] `/partners` → "Become a partner" → wizard opens on Step 1 (full hero) - [ ] Identity: name / work email / company → Next - [ ] Profile: pick **Type of team**; search country ("fra" → France); pick languages → Next (compact header from here on) - [ ] Expertise: select 1+ **Category** cards; add **Skills** (click a suggestion, type one + Enter, drive the ↑/↓ autocomplete); optionally fill **Notes** - [ ] Country dropdown opens without being clipped by the modal, and clicking inside it does **not** close the wizard - [ ] Commercials → Submit → **in-modal "Thanks, we'll be in touch!"**; Network shows POST `/api/partner-application` `200` - [ ] Partner record lands with the chosen categories in `partnerScope`, plus `skills`, `applicationNotes`, `slug` from company, `reviewed: false`, `partnerTier: 'NEW'` - [ ] Re-submit same email + different city → Partner updates; `validationStage`/`reviewed`/`partnerTier` preserved - [ ] Back/Next preserves entered values; Reset on close; mobile single-column / chips wrap --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
546 lines
18 KiB
TypeScript
546 lines
18 KiB
TypeScript
import type { MessageDescriptor } from '@lingui/core';
|
|
import { msg } from '@lingui/core/macro';
|
|
|
|
import type { PartnerApplicationState } from './use-partner-application-state';
|
|
|
|
export const PARTNER_APPLICATION_STEP_IDS = [
|
|
'identity',
|
|
'profile',
|
|
'expertise',
|
|
'commercials',
|
|
] as const;
|
|
|
|
export type PartnerApplicationStepId =
|
|
(typeof PARTNER_APPLICATION_STEP_IDS)[number];
|
|
|
|
export const PARTNER_TYPE_OF_TEAM_VALUES = ['SOLO', 'AGENCY'] as const;
|
|
export type PartnerTypeOfTeam = (typeof PARTNER_TYPE_OF_TEAM_VALUES)[number];
|
|
|
|
export const PARTNER_TYPE_OF_TEAM_OPTIONS: ReadonlyArray<{
|
|
value: PartnerTypeOfTeam;
|
|
label: MessageDescriptor;
|
|
}> = [
|
|
{ value: 'SOLO', label: msg`Solo` },
|
|
{ value: 'AGENCY', label: msg`Agency` },
|
|
];
|
|
|
|
export const PARTNER_SCOPE_VALUES = [
|
|
'ADVISORY',
|
|
'SOLUTIONING',
|
|
'DEVELOPMENT',
|
|
'HOSTING',
|
|
'SUPPORT',
|
|
] as const;
|
|
export type PartnerScopeValue = (typeof PARTNER_SCOPE_VALUES)[number];
|
|
|
|
export const PARTNER_SCOPE_OPTIONS: ReadonlyArray<{
|
|
value: PartnerScopeValue;
|
|
label: MessageDescriptor;
|
|
description: MessageDescriptor;
|
|
examples: MessageDescriptor;
|
|
}> = [
|
|
{
|
|
value: 'ADVISORY',
|
|
label: msg`Advisory & Discovery`,
|
|
description: msg`Upfront consulting, scoping, strategy.`,
|
|
examples: msg`CRM audit · Requirements · Process mapping · ROI · RevOps · Vendor selection`,
|
|
},
|
|
{
|
|
value: 'SOLUTIONING',
|
|
label: msg`Solutioning`,
|
|
description: msg`What an admin can do without writing code.`,
|
|
examples: msg`Data modeling · Migrations · No-code workflows · Dashboards · SSO/SCIM · Integrations`,
|
|
},
|
|
{
|
|
value: 'DEVELOPMENT',
|
|
label: msg`Custom Development`,
|
|
description: msg`Anything that needs a developer.`,
|
|
examples: msg`Custom Apps · Scripts · AI/agent integrations`,
|
|
},
|
|
{
|
|
value: 'HOSTING',
|
|
label: msg`Hosting & Infrastructure`,
|
|
description: msg`Anything that needs devops skills.`,
|
|
examples: msg`Self-hosted (Docker/K8s) · Cloud architecture · Scaling · Security · Monitoring`,
|
|
},
|
|
{
|
|
value: 'SUPPORT',
|
|
label: msg`Training, Adoption & Support`,
|
|
description: msg`User-side rollout & ongoing support.`,
|
|
examples: msg`Onboarding · Documentation · Change management · L1/L2 support · Managed services`,
|
|
},
|
|
];
|
|
|
|
export const PARTNER_SKILL_SUGGESTIONS: ReadonlyArray<string> = [
|
|
'React',
|
|
'TypeScript',
|
|
'Node.js',
|
|
'Python',
|
|
'PostgreSQL',
|
|
'GraphQL',
|
|
'n8n',
|
|
'Zapier',
|
|
'Make',
|
|
'Salesforce',
|
|
'HubSpot',
|
|
'SAP',
|
|
'Shopify',
|
|
'Stripe',
|
|
'Docker',
|
|
'Kubernetes',
|
|
'AWS',
|
|
'GCP',
|
|
];
|
|
|
|
export const PARTNER_COUNTRY_VALUES = [
|
|
'AFGHANISTAN',
|
|
'ALBANIA',
|
|
'ALGERIA',
|
|
'ANDORRA',
|
|
'ANGOLA',
|
|
'ANTIGUA_AND_BARBUDA',
|
|
'ARGENTINA',
|
|
'ARMENIA',
|
|
'AUSTRALIA',
|
|
'AUSTRIA',
|
|
'AZERBAIJAN',
|
|
'BAHAMAS',
|
|
'BAHRAIN',
|
|
'BANGLADESH',
|
|
'BARBADOS',
|
|
'BELARUS',
|
|
'BELGIUM',
|
|
'BELIZE',
|
|
'BENIN',
|
|
'BHUTAN',
|
|
'BOLIVIA',
|
|
'BOSNIA_AND_HERZEGOVINA',
|
|
'BOTSWANA',
|
|
'BRAZIL',
|
|
'BRUNEI',
|
|
'BULGARIA',
|
|
'BURKINA_FASO',
|
|
'BURUNDI',
|
|
'CAMBODIA',
|
|
'CAMEROON',
|
|
'CANADA',
|
|
'CAPE_VERDE',
|
|
'CENTRAL_AFRICAN_REPUBLIC',
|
|
'CHAD',
|
|
'CHILE',
|
|
'CHINA',
|
|
'COLOMBIA',
|
|
'COMOROS',
|
|
'CONGO',
|
|
'DR_CONGO',
|
|
'COSTA_RICA',
|
|
'CROATIA',
|
|
'CUBA',
|
|
'CYPRUS',
|
|
'CZECH_REPUBLIC',
|
|
'DENMARK',
|
|
'DJIBOUTI',
|
|
'DOMINICA',
|
|
'DOMINICAN_REPUBLIC',
|
|
'ECUADOR',
|
|
'EGYPT',
|
|
'EL_SALVADOR',
|
|
'EQUATORIAL_GUINEA',
|
|
'ERITREA',
|
|
'ESTONIA',
|
|
'ESWATINI',
|
|
'ETHIOPIA',
|
|
'FIJI',
|
|
'FINLAND',
|
|
'FRANCE',
|
|
'GABON',
|
|
'GAMBIA',
|
|
'GEORGIA',
|
|
'GERMANY',
|
|
'GHANA',
|
|
'GREECE',
|
|
'GRENADA',
|
|
'GUATEMALA',
|
|
'GUINEA',
|
|
'GUINEA_BISSAU',
|
|
'GUYANA',
|
|
'HAITI',
|
|
'HONDURAS',
|
|
'HUNGARY',
|
|
'ICELAND',
|
|
'INDIA',
|
|
'INDONESIA',
|
|
'IRAN',
|
|
'IRAQ',
|
|
'IRELAND',
|
|
'ISRAEL',
|
|
'ITALY',
|
|
'IVORY_COAST',
|
|
'JAMAICA',
|
|
'JAPAN',
|
|
'JORDAN',
|
|
'KAZAKHSTAN',
|
|
'KENYA',
|
|
'KIRIBATI',
|
|
'KOSOVO',
|
|
'KUWAIT',
|
|
'KYRGYZSTAN',
|
|
'LAOS',
|
|
'LATVIA',
|
|
'LEBANON',
|
|
'LESOTHO',
|
|
'LIBERIA',
|
|
'LIBYA',
|
|
'LIECHTENSTEIN',
|
|
'LITHUANIA',
|
|
'LUXEMBOURG',
|
|
'MADAGASCAR',
|
|
'MALAWI',
|
|
'MALAYSIA',
|
|
'MALDIVES',
|
|
'MALI',
|
|
'MALTA',
|
|
'MARSHALL_ISLANDS',
|
|
'MAURITANIA',
|
|
'MAURITIUS',
|
|
'MEXICO',
|
|
'MICRONESIA',
|
|
'MOLDOVA',
|
|
'MONACO',
|
|
'MONGOLIA',
|
|
'MONTENEGRO',
|
|
'MOROCCO',
|
|
'MOZAMBIQUE',
|
|
'MYANMAR',
|
|
'NAMIBIA',
|
|
'NAURU',
|
|
'NEPAL',
|
|
'NETHERLANDS',
|
|
'NEW_ZEALAND',
|
|
'NICARAGUA',
|
|
'NIGER',
|
|
'NIGERIA',
|
|
'NORTH_KOREA',
|
|
'NORTH_MACEDONIA',
|
|
'NORWAY',
|
|
'OMAN',
|
|
'PAKISTAN',
|
|
'PALAU',
|
|
'PALESTINE',
|
|
'PANAMA',
|
|
'PAPUA_NEW_GUINEA',
|
|
'PARAGUAY',
|
|
'PERU',
|
|
'PHILIPPINES',
|
|
'POLAND',
|
|
'PORTUGAL',
|
|
'QATAR',
|
|
'ROMANIA',
|
|
'RUSSIA',
|
|
'RWANDA',
|
|
'SAINT_KITTS_AND_NEVIS',
|
|
'SAINT_LUCIA',
|
|
'SAINT_VINCENT',
|
|
'SAMOA',
|
|
'SAN_MARINO',
|
|
'SAO_TOME_AND_PRINCIPE',
|
|
'SAUDI_ARABIA',
|
|
'SENEGAL',
|
|
'SERBIA',
|
|
'SEYCHELLES',
|
|
'SIERRA_LEONE',
|
|
'SINGAPORE',
|
|
'SLOVAKIA',
|
|
'SLOVENIA',
|
|
'SOLOMON_ISLANDS',
|
|
'SOMALIA',
|
|
'SOUTH_AFRICA',
|
|
'SOUTH_KOREA',
|
|
'SOUTH_SUDAN',
|
|
'SPAIN',
|
|
'SRI_LANKA',
|
|
'SUDAN',
|
|
'SURINAME',
|
|
'SWEDEN',
|
|
'SWITZERLAND',
|
|
'SYRIA',
|
|
'TAIWAN',
|
|
'TAJIKISTAN',
|
|
'TANZANIA',
|
|
'THAILAND',
|
|
'TIMOR_LESTE',
|
|
'TOGO',
|
|
'TONGA',
|
|
'TRINIDAD_AND_TOBAGO',
|
|
'TUNISIA',
|
|
'TURKEY',
|
|
'TURKMENISTAN',
|
|
'TUVALU',
|
|
'UGANDA',
|
|
'UKRAINE',
|
|
'UNITED_ARAB_EMIRATES',
|
|
'UNITED_KINGDOM',
|
|
'UNITED_STATES',
|
|
'URUGUAY',
|
|
'UZBEKISTAN',
|
|
'VANUATU',
|
|
'VATICAN',
|
|
'VENEZUELA',
|
|
'VIETNAM',
|
|
'YEMEN',
|
|
'ZAMBIA',
|
|
'ZIMBABWE',
|
|
] as const;
|
|
export type PartnerCountryValue = (typeof PARTNER_COUNTRY_VALUES)[number];
|
|
|
|
export const PARTNER_COUNTRY_OPTIONS: ReadonlyArray<{
|
|
value: PartnerCountryValue;
|
|
label: MessageDescriptor;
|
|
}> = [
|
|
{ value: 'AFGHANISTAN', label: msg`Afghanistan 🇦🇫` },
|
|
{ value: 'ALBANIA', label: msg`Albania 🇦🇱` },
|
|
{ value: 'ALGERIA', label: msg`Algeria 🇩🇿` },
|
|
{ value: 'ANDORRA', label: msg`Andorra 🇦🇩` },
|
|
{ value: 'ANGOLA', label: msg`Angola 🇦🇴` },
|
|
{ value: 'ANTIGUA_AND_BARBUDA', label: msg`Antigua & Barbuda 🇦🇬` },
|
|
{ value: 'ARGENTINA', label: msg`Argentina 🇦🇷` },
|
|
{ value: 'ARMENIA', label: msg`Armenia 🇦🇲` },
|
|
{ value: 'AUSTRALIA', label: msg`Australia 🇦🇺` },
|
|
{ value: 'AUSTRIA', label: msg`Austria 🇦🇹` },
|
|
{ value: 'AZERBAIJAN', label: msg`Azerbaijan 🇦🇿` },
|
|
{ value: 'BAHAMAS', label: msg`Bahamas 🇧🇸` },
|
|
{ value: 'BAHRAIN', label: msg`Bahrain 🇧🇭` },
|
|
{ value: 'BANGLADESH', label: msg`Bangladesh 🇧🇩` },
|
|
{ value: 'BARBADOS', label: msg`Barbados 🇧🇧` },
|
|
{ value: 'BELARUS', label: msg`Belarus 🇧🇾` },
|
|
{ value: 'BELGIUM', label: msg`Belgium 🇧🇪` },
|
|
{ value: 'BELIZE', label: msg`Belize 🇧🇿` },
|
|
{ value: 'BENIN', label: msg`Benin 🇧🇯` },
|
|
{ value: 'BHUTAN', label: msg`Bhutan 🇧🇹` },
|
|
{ value: 'BOLIVIA', label: msg`Bolivia 🇧🇴` },
|
|
{ value: 'BOSNIA_AND_HERZEGOVINA', label: msg`Bosnia & Herzegovina 🇧🇦` },
|
|
{ value: 'BOTSWANA', label: msg`Botswana 🇧🇼` },
|
|
{ value: 'BRAZIL', label: msg`Brazil 🇧🇷` },
|
|
{ value: 'BRUNEI', label: msg`Brunei 🇧🇳` },
|
|
{ value: 'BULGARIA', label: msg`Bulgaria 🇧🇬` },
|
|
{ value: 'BURKINA_FASO', label: msg`Burkina Faso 🇧🇫` },
|
|
{ value: 'BURUNDI', label: msg`Burundi 🇧🇮` },
|
|
{ value: 'CAMBODIA', label: msg`Cambodia 🇰🇭` },
|
|
{ value: 'CAMEROON', label: msg`Cameroon 🇨🇲` },
|
|
{ value: 'CANADA', label: msg`Canada 🇨🇦` },
|
|
{ value: 'CAPE_VERDE', label: msg`Cape Verde 🇨🇻` },
|
|
{
|
|
value: 'CENTRAL_AFRICAN_REPUBLIC',
|
|
label: msg`Central African Republic 🇨🇫`,
|
|
},
|
|
{ value: 'CHAD', label: msg`Chad 🇹🇩` },
|
|
{ value: 'CHILE', label: msg`Chile 🇨🇱` },
|
|
{ value: 'CHINA', label: msg`China 🇨🇳` },
|
|
{ value: 'COLOMBIA', label: msg`Colombia 🇨🇴` },
|
|
{ value: 'COMOROS', label: msg`Comoros 🇰🇲` },
|
|
{ value: 'CONGO', label: msg`Congo 🇨🇬` },
|
|
{ value: 'DR_CONGO', label: msg`DR Congo 🇨🇩` },
|
|
{ value: 'COSTA_RICA', label: msg`Costa Rica 🇨🇷` },
|
|
{ value: 'CROATIA', label: msg`Croatia 🇭🇷` },
|
|
{ value: 'CUBA', label: msg`Cuba 🇨🇺` },
|
|
{ value: 'CYPRUS', label: msg`Cyprus 🇨🇾` },
|
|
{ value: 'CZECH_REPUBLIC', label: msg`Czech Republic 🇨🇿` },
|
|
{ value: 'DENMARK', label: msg`Denmark 🇩🇰` },
|
|
{ value: 'DJIBOUTI', label: msg`Djibouti 🇩🇯` },
|
|
{ value: 'DOMINICA', label: msg`Dominica 🇩🇲` },
|
|
{ value: 'DOMINICAN_REPUBLIC', label: msg`Dominican Republic 🇩🇴` },
|
|
{ value: 'ECUADOR', label: msg`Ecuador 🇪🇨` },
|
|
{ value: 'EGYPT', label: msg`Egypt 🇪🇬` },
|
|
{ value: 'EL_SALVADOR', label: msg`El Salvador 🇸🇻` },
|
|
{ value: 'EQUATORIAL_GUINEA', label: msg`Equatorial Guinea 🇬🇶` },
|
|
{ value: 'ERITREA', label: msg`Eritrea 🇪🇷` },
|
|
{ value: 'ESTONIA', label: msg`Estonia 🇪🇪` },
|
|
{ value: 'ESWATINI', label: msg`Eswatini 🇸🇿` },
|
|
{ value: 'ETHIOPIA', label: msg`Ethiopia 🇪🇹` },
|
|
{ value: 'FIJI', label: msg`Fiji 🇫🇯` },
|
|
{ value: 'FINLAND', label: msg`Finland 🇫🇮` },
|
|
{ value: 'FRANCE', label: msg`France 🇫🇷` },
|
|
{ value: 'GABON', label: msg`Gabon 🇬🇦` },
|
|
{ value: 'GAMBIA', label: msg`Gambia 🇬🇲` },
|
|
{ value: 'GEORGIA', label: msg`Georgia 🇬🇪` },
|
|
{ value: 'GERMANY', label: msg`Germany 🇩🇪` },
|
|
{ value: 'GHANA', label: msg`Ghana 🇬🇭` },
|
|
{ value: 'GREECE', label: msg`Greece 🇬🇷` },
|
|
{ value: 'GRENADA', label: msg`Grenada 🇬🇩` },
|
|
{ value: 'GUATEMALA', label: msg`Guatemala 🇬🇹` },
|
|
{ value: 'GUINEA', label: msg`Guinea 🇬🇳` },
|
|
{ value: 'GUINEA_BISSAU', label: msg`Guinea-Bissau 🇬🇼` },
|
|
{ value: 'GUYANA', label: msg`Guyana 🇬🇾` },
|
|
{ value: 'HAITI', label: msg`Haiti 🇭🇹` },
|
|
{ value: 'HONDURAS', label: msg`Honduras 🇭🇳` },
|
|
{ value: 'HUNGARY', label: msg`Hungary 🇭🇺` },
|
|
{ value: 'ICELAND', label: msg`Iceland 🇮🇸` },
|
|
{ value: 'INDIA', label: msg`India 🇮🇳` },
|
|
{ value: 'INDONESIA', label: msg`Indonesia 🇮🇩` },
|
|
{ value: 'IRAN', label: msg`Iran 🇮🇷` },
|
|
{ value: 'IRAQ', label: msg`Iraq 🇮🇶` },
|
|
{ value: 'IRELAND', label: msg`Ireland 🇮🇪` },
|
|
{ value: 'ISRAEL', label: msg`Israel 🇮🇱` },
|
|
{ value: 'ITALY', label: msg`Italy 🇮🇹` },
|
|
{ value: 'IVORY_COAST', label: msg`Ivory Coast 🇨🇮` },
|
|
{ value: 'JAMAICA', label: msg`Jamaica 🇯🇲` },
|
|
{ value: 'JAPAN', label: msg`Japan 🇯🇵` },
|
|
{ value: 'JORDAN', label: msg`Jordan 🇯🇴` },
|
|
{ value: 'KAZAKHSTAN', label: msg`Kazakhstan 🇰🇿` },
|
|
{ value: 'KENYA', label: msg`Kenya 🇰🇪` },
|
|
{ value: 'KIRIBATI', label: msg`Kiribati 🇰🇮` },
|
|
{ value: 'KOSOVO', label: msg`Kosovo 🇽🇰` },
|
|
{ value: 'KUWAIT', label: msg`Kuwait 🇰🇼` },
|
|
{ value: 'KYRGYZSTAN', label: msg`Kyrgyzstan 🇰🇬` },
|
|
{ value: 'LAOS', label: msg`Laos 🇱🇦` },
|
|
{ value: 'LATVIA', label: msg`Latvia 🇱🇻` },
|
|
{ value: 'LEBANON', label: msg`Lebanon 🇱🇧` },
|
|
{ value: 'LESOTHO', label: msg`Lesotho 🇱🇸` },
|
|
{ value: 'LIBERIA', label: msg`Liberia 🇱🇷` },
|
|
{ value: 'LIBYA', label: msg`Libya 🇱🇾` },
|
|
{ value: 'LIECHTENSTEIN', label: msg`Liechtenstein 🇱🇮` },
|
|
{ value: 'LITHUANIA', label: msg`Lithuania 🇱🇹` },
|
|
{ value: 'LUXEMBOURG', label: msg`Luxembourg 🇱🇺` },
|
|
{ value: 'MADAGASCAR', label: msg`Madagascar 🇲🇬` },
|
|
{ value: 'MALAWI', label: msg`Malawi 🇲🇼` },
|
|
{ value: 'MALAYSIA', label: msg`Malaysia 🇲🇾` },
|
|
{ value: 'MALDIVES', label: msg`Maldives 🇲🇻` },
|
|
{ value: 'MALI', label: msg`Mali 🇲🇱` },
|
|
{ value: 'MALTA', label: msg`Malta 🇲🇹` },
|
|
{ value: 'MARSHALL_ISLANDS', label: msg`Marshall Islands 🇲🇭` },
|
|
{ value: 'MAURITANIA', label: msg`Mauritania 🇲🇷` },
|
|
{ value: 'MAURITIUS', label: msg`Mauritius 🇲🇺` },
|
|
{ value: 'MEXICO', label: msg`Mexico 🇲🇽` },
|
|
{ value: 'MICRONESIA', label: msg`Micronesia 🇫🇲` },
|
|
{ value: 'MOLDOVA', label: msg`Moldova 🇲🇩` },
|
|
{ value: 'MONACO', label: msg`Monaco 🇲🇨` },
|
|
{ value: 'MONGOLIA', label: msg`Mongolia 🇲🇳` },
|
|
{ value: 'MONTENEGRO', label: msg`Montenegro 🇲🇪` },
|
|
{ value: 'MOROCCO', label: msg`Morocco 🇲🇦` },
|
|
{ value: 'MOZAMBIQUE', label: msg`Mozambique 🇲🇿` },
|
|
{ value: 'MYANMAR', label: msg`Myanmar 🇲🇲` },
|
|
{ value: 'NAMIBIA', label: msg`Namibia 🇳🇦` },
|
|
{ value: 'NAURU', label: msg`Nauru 🇳🇷` },
|
|
{ value: 'NEPAL', label: msg`Nepal 🇳🇵` },
|
|
{ value: 'NETHERLANDS', label: msg`Netherlands 🇳🇱` },
|
|
{ value: 'NEW_ZEALAND', label: msg`New Zealand 🇳🇿` },
|
|
{ value: 'NICARAGUA', label: msg`Nicaragua 🇳🇮` },
|
|
{ value: 'NIGER', label: msg`Niger 🇳🇪` },
|
|
{ value: 'NIGERIA', label: msg`Nigeria 🇳🇬` },
|
|
{ value: 'NORTH_KOREA', label: msg`North Korea 🇰🇵` },
|
|
{ value: 'NORTH_MACEDONIA', label: msg`North Macedonia 🇲🇰` },
|
|
{ value: 'NORWAY', label: msg`Norway 🇳🇴` },
|
|
{ value: 'OMAN', label: msg`Oman 🇴🇲` },
|
|
{ value: 'PAKISTAN', label: msg`Pakistan 🇵🇰` },
|
|
{ value: 'PALAU', label: msg`Palau 🇵🇼` },
|
|
{ value: 'PALESTINE', label: msg`Palestine 🇵🇸` },
|
|
{ value: 'PANAMA', label: msg`Panama 🇵🇦` },
|
|
{ value: 'PAPUA_NEW_GUINEA', label: msg`Papua New Guinea 🇵🇬` },
|
|
{ value: 'PARAGUAY', label: msg`Paraguay 🇵🇾` },
|
|
{ value: 'PERU', label: msg`Peru 🇵🇪` },
|
|
{ value: 'PHILIPPINES', label: msg`Philippines 🇵🇭` },
|
|
{ value: 'POLAND', label: msg`Poland 🇵🇱` },
|
|
{ value: 'PORTUGAL', label: msg`Portugal 🇵🇹` },
|
|
{ value: 'QATAR', label: msg`Qatar 🇶🇦` },
|
|
{ value: 'ROMANIA', label: msg`Romania 🇷🇴` },
|
|
{ value: 'RUSSIA', label: msg`Russia 🇷🇺` },
|
|
{ value: 'RWANDA', label: msg`Rwanda 🇷🇼` },
|
|
{ value: 'SAINT_KITTS_AND_NEVIS', label: msg`Saint Kitts & Nevis 🇰🇳` },
|
|
{ value: 'SAINT_LUCIA', label: msg`Saint Lucia 🇱🇨` },
|
|
{ value: 'SAINT_VINCENT', label: msg`Saint Vincent 🇻🇨` },
|
|
{ value: 'SAMOA', label: msg`Samoa 🇼🇸` },
|
|
{ value: 'SAN_MARINO', label: msg`San Marino 🇸🇲` },
|
|
{ value: 'SAO_TOME_AND_PRINCIPE', label: msg`São Tomé & Príncipe 🇸🇹` },
|
|
{ value: 'SAUDI_ARABIA', label: msg`Saudi Arabia 🇸🇦` },
|
|
{ value: 'SENEGAL', label: msg`Senegal 🇸🇳` },
|
|
{ value: 'SERBIA', label: msg`Serbia 🇷🇸` },
|
|
{ value: 'SEYCHELLES', label: msg`Seychelles 🇸🇨` },
|
|
{ value: 'SIERRA_LEONE', label: msg`Sierra Leone 🇸🇱` },
|
|
{ value: 'SINGAPORE', label: msg`Singapore 🇸🇬` },
|
|
{ value: 'SLOVAKIA', label: msg`Slovakia 🇸🇰` },
|
|
{ value: 'SLOVENIA', label: msg`Slovenia 🇸🇮` },
|
|
{ value: 'SOLOMON_ISLANDS', label: msg`Solomon Islands 🇸🇧` },
|
|
{ value: 'SOMALIA', label: msg`Somalia 🇸🇴` },
|
|
{ value: 'SOUTH_AFRICA', label: msg`South Africa 🇿🇦` },
|
|
{ value: 'SOUTH_KOREA', label: msg`South Korea 🇰🇷` },
|
|
{ value: 'SOUTH_SUDAN', label: msg`South Sudan 🇸🇸` },
|
|
{ value: 'SPAIN', label: msg`Spain 🇪🇸` },
|
|
{ value: 'SRI_LANKA', label: msg`Sri Lanka 🇱🇰` },
|
|
{ value: 'SUDAN', label: msg`Sudan 🇸🇩` },
|
|
{ value: 'SURINAME', label: msg`Suriname 🇸🇷` },
|
|
{ value: 'SWEDEN', label: msg`Sweden 🇸🇪` },
|
|
{ value: 'SWITZERLAND', label: msg`Switzerland 🇨🇭` },
|
|
{ value: 'SYRIA', label: msg`Syria 🇸🇾` },
|
|
{ value: 'TAIWAN', label: msg`Taiwan 🇹🇼` },
|
|
{ value: 'TAJIKISTAN', label: msg`Tajikistan 🇹🇯` },
|
|
{ value: 'TANZANIA', label: msg`Tanzania 🇹🇿` },
|
|
{ value: 'THAILAND', label: msg`Thailand 🇹🇭` },
|
|
{ value: 'TIMOR_LESTE', label: msg`Timor-Leste 🇹🇱` },
|
|
{ value: 'TOGO', label: msg`Togo 🇹🇬` },
|
|
{ value: 'TONGA', label: msg`Tonga 🇹🇴` },
|
|
{ value: 'TRINIDAD_AND_TOBAGO', label: msg`Trinidad & Tobago 🇹🇹` },
|
|
{ value: 'TUNISIA', label: msg`Tunisia 🇹🇳` },
|
|
{ value: 'TURKEY', label: msg`Turkey 🇹🇷` },
|
|
{ value: 'TURKMENISTAN', label: msg`Turkmenistan 🇹🇲` },
|
|
{ value: 'TUVALU', label: msg`Tuvalu 🇹🇻` },
|
|
{ value: 'UGANDA', label: msg`Uganda 🇺🇬` },
|
|
{ value: 'UKRAINE', label: msg`Ukraine 🇺🇦` },
|
|
{ value: 'UNITED_ARAB_EMIRATES', label: msg`UAE 🇦🇪` },
|
|
{ value: 'UNITED_KINGDOM', label: msg`UK 🇬🇧` },
|
|
{ value: 'UNITED_STATES', label: msg`USA 🇺🇸` },
|
|
{ value: 'URUGUAY', label: msg`Uruguay 🇺🇾` },
|
|
{ value: 'UZBEKISTAN', label: msg`Uzbekistan 🇺🇿` },
|
|
{ value: 'VANUATU', label: msg`Vanuatu 🇻🇺` },
|
|
{ value: 'VATICAN', label: msg`Vatican 🇻🇦` },
|
|
{ value: 'VENEZUELA', label: msg`Venezuela 🇻🇪` },
|
|
{ value: 'VIETNAM', label: msg`Vietnam 🇻🇳` },
|
|
{ value: 'YEMEN', label: msg`Yemen 🇾🇪` },
|
|
{ value: 'ZAMBIA', label: msg`Zambia 🇿🇲` },
|
|
{ value: 'ZIMBABWE', label: msg`Zimbabwe 🇿🇼` },
|
|
];
|
|
|
|
export const PARTNER_LANGUAGE_VALUES = [
|
|
'ENGLISH',
|
|
'FRENCH',
|
|
'GERMAN',
|
|
'SPANISH',
|
|
'PORTUGUESE',
|
|
'ITALIAN',
|
|
'DUTCH',
|
|
'ARABIC',
|
|
'CHINESE',
|
|
'JAPANESE',
|
|
'RUSSIAN',
|
|
'HINDI',
|
|
] as const;
|
|
export type PartnerLanguageValue = (typeof PARTNER_LANGUAGE_VALUES)[number];
|
|
|
|
export const PARTNER_LANGUAGE_OPTIONS: ReadonlyArray<{
|
|
value: PartnerLanguageValue;
|
|
label: MessageDescriptor;
|
|
}> = [
|
|
{ value: 'ENGLISH', label: msg`English` },
|
|
{ value: 'FRENCH', label: msg`French` },
|
|
{ value: 'GERMAN', label: msg`German` },
|
|
{ value: 'SPANISH', label: msg`Spanish` },
|
|
{ value: 'PORTUGUESE', label: msg`Portuguese` },
|
|
{ value: 'ITALIAN', label: msg`Italian` },
|
|
{ value: 'DUTCH', label: msg`Dutch` },
|
|
{ value: 'ARABIC', label: msg`Arabic` },
|
|
{ value: 'CHINESE', label: msg`Chinese` },
|
|
{ value: 'JAPANESE', label: msg`Japanese` },
|
|
{ value: 'RUSSIAN', label: msg`Russian` },
|
|
{ value: 'HINDI', label: msg`Hindi` },
|
|
];
|
|
|
|
// Per-step required field names. The wizard reducer reads this to gate `goNext`.
|
|
export const PARTNER_APPLICATION_STEP_REQUIRED_FIELDS: Record<
|
|
PartnerApplicationStepId,
|
|
ReadonlyArray<keyof PartnerApplicationState>
|
|
> = {
|
|
identity: ['name', 'email', 'company'],
|
|
profile: ['country', 'typeOfTeam'],
|
|
expertise: ['partnerScope'],
|
|
commercials: [],
|
|
};
|