data expanded
Browse files- data/intake/choices/budget.yaml +24 -0
- data/intake/choices/education.yaml +17 -0
- data/intake/choices/experience.yaml +11 -0
- data/intake/choices/fallback_countries.yaml +84 -0
- data/intake/choices/family.yaml +13 -0
- data/intake/choices/languages.yaml +62 -0
- data/intake/choices/occupation.yaml +29 -0
- data/intake/choices/residence_status.yaml +20 -0
- data/intake/choices/timeline.yaml +12 -0
- data/intake/personas.yaml +129 -0
- ui/intake/choices.py +13 -133
- ui/intake/examples.py +46 -24
- ui/intake/loader.py +30 -0
- ui/intake/panel.py +1 -0
data/intake/choices/budget.yaml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Under USD 2,500 savings
|
| 2 |
+
- USD 2,500-5,000 savings
|
| 3 |
+
- USD 5,000-10,000 savings
|
| 4 |
+
- USD 10,000-15,000 savings
|
| 5 |
+
- USD 15,000-25,000 savings
|
| 6 |
+
- USD 25,000-40,000 savings
|
| 7 |
+
- USD 40,000-60,000 savings
|
| 8 |
+
- USD 60,000-100,000 savings
|
| 9 |
+
- USD 100,000+ savings
|
| 10 |
+
- Monthly income under USD 1,000
|
| 11 |
+
- Monthly income USD 1,000-2,000
|
| 12 |
+
- Monthly income USD 2,000-3,500
|
| 13 |
+
- Monthly income USD 3,500-5,000
|
| 14 |
+
- Monthly income USD 5,000-8,000
|
| 15 |
+
- Monthly income USD 8,000-12,000
|
| 16 |
+
- Monthly income USD 12,000+
|
| 17 |
+
- Can show proof of funds for visa (amount flexible)
|
| 18 |
+
- Employer sponsorship available
|
| 19 |
+
- Family sponsor abroad
|
| 20 |
+
- Scholarship / grant funding
|
| 21 |
+
- Can invest USD 50,000+ (business / golden visa)
|
| 22 |
+
- Can invest USD 100,000+ (business / golden visa)
|
| 23 |
+
- Prefer lower cost of living
|
| 24 |
+
- Flexible / not sure
|
data/intake/choices/education.yaml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- No formal schooling
|
| 2 |
+
- Some primary / elementary school
|
| 3 |
+
- High school / secondary (incomplete)
|
| 4 |
+
- High school / secondary (completed)
|
| 5 |
+
- Vocational / trade certificate
|
| 6 |
+
- Associate degree / diploma
|
| 7 |
+
- Bachelor's degree (in progress)
|
| 8 |
+
- Bachelor's degree
|
| 9 |
+
- Master's degree (in progress)
|
| 10 |
+
- Master's degree
|
| 11 |
+
- PhD / doctorate (in progress)
|
| 12 |
+
- PhD / doctorate
|
| 13 |
+
- Professional degree (MD, JD, DDS, etc.)
|
| 14 |
+
- Postgraduate diploma / certificate
|
| 15 |
+
- Professional license or board certification
|
| 16 |
+
- Currently studying (secondary)
|
| 17 |
+
- Currently studying (university)
|
data/intake/choices/experience.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- No professional experience
|
| 2 |
+
- Internship / trainee only
|
| 3 |
+
- Less than 1 year
|
| 4 |
+
- 1-2 years
|
| 5 |
+
- 2-3 years
|
| 6 |
+
- 3-5 years
|
| 7 |
+
- 5-7 years
|
| 8 |
+
- 7-10 years
|
| 9 |
+
- 10-15 years
|
| 10 |
+
- 15-20 years
|
| 11 |
+
- 20+ years
|
data/intake/choices/fallback_countries.yaml
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Afghanistan
|
| 2 |
+
- Algeria
|
| 3 |
+
- Argentina
|
| 4 |
+
- Australia
|
| 5 |
+
- Austria
|
| 6 |
+
- Bangladesh
|
| 7 |
+
- Belgium
|
| 8 |
+
- Bolivia
|
| 9 |
+
- Brazil
|
| 10 |
+
- Cambodia
|
| 11 |
+
- Cameroon
|
| 12 |
+
- Canada
|
| 13 |
+
- Chile
|
| 14 |
+
- China
|
| 15 |
+
- Colombia
|
| 16 |
+
- Costa Rica
|
| 17 |
+
- Croatia
|
| 18 |
+
- Czech Republic
|
| 19 |
+
- Denmark
|
| 20 |
+
- Dominican Republic
|
| 21 |
+
- Ecuador
|
| 22 |
+
- Egypt
|
| 23 |
+
- Ethiopia
|
| 24 |
+
- Finland
|
| 25 |
+
- France
|
| 26 |
+
- Germany
|
| 27 |
+
- Ghana
|
| 28 |
+
- Greece
|
| 29 |
+
- Hong Kong
|
| 30 |
+
- Hungary
|
| 31 |
+
- India
|
| 32 |
+
- Indonesia
|
| 33 |
+
- Iran
|
| 34 |
+
- Iraq
|
| 35 |
+
- Ireland
|
| 36 |
+
- Israel
|
| 37 |
+
- Italy
|
| 38 |
+
- Jamaica
|
| 39 |
+
- Japan
|
| 40 |
+
- Jordan
|
| 41 |
+
- Kenya
|
| 42 |
+
- South Korea
|
| 43 |
+
- Kuwait
|
| 44 |
+
- Lebanon
|
| 45 |
+
- Malaysia
|
| 46 |
+
- Mexico
|
| 47 |
+
- Morocco
|
| 48 |
+
- Myanmar
|
| 49 |
+
- Nepal
|
| 50 |
+
- Netherlands
|
| 51 |
+
- New Zealand
|
| 52 |
+
- Nigeria
|
| 53 |
+
- Norway
|
| 54 |
+
- Pakistan
|
| 55 |
+
- Peru
|
| 56 |
+
- Philippines
|
| 57 |
+
- Poland
|
| 58 |
+
- Portugal
|
| 59 |
+
- Qatar
|
| 60 |
+
- Romania
|
| 61 |
+
- Russia
|
| 62 |
+
- Saudi Arabia
|
| 63 |
+
- Senegal
|
| 64 |
+
- Serbia
|
| 65 |
+
- Singapore
|
| 66 |
+
- South Africa
|
| 67 |
+
- Spain
|
| 68 |
+
- Sri Lanka
|
| 69 |
+
- Sweden
|
| 70 |
+
- Switzerland
|
| 71 |
+
- Taiwan
|
| 72 |
+
- Tanzania
|
| 73 |
+
- Thailand
|
| 74 |
+
- Tunisia
|
| 75 |
+
- Turkey
|
| 76 |
+
- Uganda
|
| 77 |
+
- Ukraine
|
| 78 |
+
- United Arab Emirates
|
| 79 |
+
- United Kingdom
|
| 80 |
+
- United States
|
| 81 |
+
- Uruguay
|
| 82 |
+
- Venezuela
|
| 83 |
+
- Vietnam
|
| 84 |
+
- Zimbabwe
|
data/intake/choices/family.yaml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Solo applicant
|
| 2 |
+
- Spouse / civil partner only
|
| 3 |
+
- Unmarried partner (de facto)
|
| 4 |
+
- Spouse / partner + 1 child
|
| 5 |
+
- Spouse / partner + 2 children
|
| 6 |
+
- Spouse / partner + 3+ children
|
| 7 |
+
- Dependents only (no spouse)
|
| 8 |
+
- Parent(s) relocating with me
|
| 9 |
+
- Adult child(ren) relocating with me
|
| 10 |
+
- Sibling(s) relocating with me
|
| 11 |
+
- Extended family relocating together
|
| 12 |
+
- Planning family reunification later
|
| 13 |
+
- Pet(s) must relocate with me
|
data/intake/choices/languages.yaml
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Afrikaans
|
| 2 |
+
- Albanian
|
| 3 |
+
- Amharic
|
| 4 |
+
- Arabic
|
| 5 |
+
- Armenian
|
| 6 |
+
- Bengali
|
| 7 |
+
- Bulgarian
|
| 8 |
+
- Burmese
|
| 9 |
+
- Cantonese
|
| 10 |
+
- Croatian
|
| 11 |
+
- Czech
|
| 12 |
+
- Danish
|
| 13 |
+
- Dutch
|
| 14 |
+
- English
|
| 15 |
+
- Estonian
|
| 16 |
+
- Farsi / Persian
|
| 17 |
+
- Filipino / Tagalog
|
| 18 |
+
- Finnish
|
| 19 |
+
- French
|
| 20 |
+
- German
|
| 21 |
+
- Greek
|
| 22 |
+
- Gujarati
|
| 23 |
+
- Hausa
|
| 24 |
+
- Hebrew
|
| 25 |
+
- Hindi
|
| 26 |
+
- Hungarian
|
| 27 |
+
- Igbo
|
| 28 |
+
- Indonesian
|
| 29 |
+
- Italian
|
| 30 |
+
- Japanese
|
| 31 |
+
- Kannada
|
| 32 |
+
- Khmer
|
| 33 |
+
- Korean
|
| 34 |
+
- Lao
|
| 35 |
+
- Latvian
|
| 36 |
+
- Lithuanian
|
| 37 |
+
- Malay
|
| 38 |
+
- Malayalam
|
| 39 |
+
- Mandarin Chinese
|
| 40 |
+
- Marathi
|
| 41 |
+
- Nepali
|
| 42 |
+
- Norwegian
|
| 43 |
+
- Polish
|
| 44 |
+
- Portuguese
|
| 45 |
+
- Punjabi
|
| 46 |
+
- Romanian
|
| 47 |
+
- Russian
|
| 48 |
+
- Serbian
|
| 49 |
+
- Sinhala
|
| 50 |
+
- Slovak
|
| 51 |
+
- Somali
|
| 52 |
+
- Spanish
|
| 53 |
+
- Swahili
|
| 54 |
+
- Swedish
|
| 55 |
+
- Tamil
|
| 56 |
+
- Telugu
|
| 57 |
+
- Thai
|
| 58 |
+
- Turkish
|
| 59 |
+
- Ukrainian
|
| 60 |
+
- Urdu
|
| 61 |
+
- Vietnamese
|
| 62 |
+
- Yoruba
|
data/intake/choices/occupation.yaml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Software / IT
|
| 2 |
+
- Data / AI / analytics
|
| 3 |
+
- Engineering (non-software)
|
| 4 |
+
- Healthcare (clinical)
|
| 5 |
+
- Healthcare (non-clinical / admin)
|
| 6 |
+
- Nursing / caregiving
|
| 7 |
+
- Education / teaching
|
| 8 |
+
- Research / academia
|
| 9 |
+
- Finance / accounting
|
| 10 |
+
- Legal / compliance
|
| 11 |
+
- Sales / marketing
|
| 12 |
+
- Design / creative / media
|
| 13 |
+
- Hospitality / food service
|
| 14 |
+
- Logistics / supply chain
|
| 15 |
+
- Manufacturing / production
|
| 16 |
+
- Construction / trades
|
| 17 |
+
- Agriculture / farming
|
| 18 |
+
- Retail / customer service
|
| 19 |
+
- Government / public sector
|
| 20 |
+
- Nonprofit / NGO
|
| 21 |
+
- Management / executive
|
| 22 |
+
- Business owner / entrepreneur
|
| 23 |
+
- Self-employed / freelancer
|
| 24 |
+
- Remote worker (overseas clients)
|
| 25 |
+
- Student / no full-time work
|
| 26 |
+
- Homemaker / caregiver (unpaid)
|
| 27 |
+
- Retired / not currently working
|
| 28 |
+
- Military / veteran
|
| 29 |
+
- Unemployed / between jobs
|
data/intake/choices/residence_status.yaml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- Citizen
|
| 2 |
+
- Permanent resident / green card equivalent
|
| 3 |
+
- Long-term resident (5+ years)
|
| 4 |
+
- Work visa / employment pass
|
| 5 |
+
- Intra-company transfer visa
|
| 6 |
+
- Skilled worker / points visa
|
| 7 |
+
- Student visa
|
| 8 |
+
- Post-study work visa
|
| 9 |
+
- Dependent / family visa
|
| 10 |
+
- Spousal / partner visa
|
| 11 |
+
- Investor / business visa
|
| 12 |
+
- Entrepreneur / startup visa
|
| 13 |
+
- Digital nomad visa
|
| 14 |
+
- Working holiday visa
|
| 15 |
+
- Refugee / asylum seeker
|
| 16 |
+
- Humanitarian / protected status
|
| 17 |
+
- Tourist / short-term stay
|
| 18 |
+
- Visa overstay / out of status
|
| 19 |
+
- Between visas / relocating soon
|
| 20 |
+
- Stateless / unclear documentation
|
data/intake/choices/timeline.yaml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
- ASAP (under 3 months)
|
| 2 |
+
- 3-6 months
|
| 3 |
+
- 6-12 months
|
| 4 |
+
- 12-18 months
|
| 5 |
+
- 18-24 months
|
| 6 |
+
- 2-3 years
|
| 7 |
+
- 3-5 years
|
| 8 |
+
- After finishing current studies
|
| 9 |
+
- After current work contract ends
|
| 10 |
+
- Long term / flexible
|
| 11 |
+
- Exploring options only
|
| 12 |
+
- Dependent on visa processing times
|
data/intake/personas.yaml
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
personas:
|
| 2 |
+
- id: india_software_engineer
|
| 3 |
+
label: India software engineer
|
| 4 |
+
profile:
|
| 5 |
+
citizenship:
|
| 6 |
+
- India
|
| 7 |
+
current_country: India
|
| 8 |
+
residence_status: Citizen
|
| 9 |
+
education: Master's degree
|
| 10 |
+
occupation: Software / IT
|
| 11 |
+
experience: 7-10 years
|
| 12 |
+
languages:
|
| 13 |
+
- English
|
| 14 |
+
- Hindi
|
| 15 |
+
budget: USD 15,000-25,000 savings
|
| 16 |
+
family: Solo applicant
|
| 17 |
+
timeline: 12-18 months
|
| 18 |
+
goals: >
|
| 19 |
+
I want to relocate for skilled work within the next 12-18 months.
|
| 20 |
+
Compare realistic countries, visa pathways, required documents,
|
| 21 |
+
approximate costs, and risks. Prioritize routes with a path to
|
| 22 |
+
permanent residence.
|
| 23 |
+
|
| 24 |
+
- id: hong_kong_student
|
| 25 |
+
label: Hong Kong student
|
| 26 |
+
profile:
|
| 27 |
+
citizenship:
|
| 28 |
+
- Hong Kong
|
| 29 |
+
current_country: Hong Kong
|
| 30 |
+
residence_status: Citizen
|
| 31 |
+
education: Bachelor's degree
|
| 32 |
+
occupation: Student / no full-time work
|
| 33 |
+
experience: Less than 1 year
|
| 34 |
+
languages:
|
| 35 |
+
- English
|
| 36 |
+
- Mandarin Chinese
|
| 37 |
+
budget: USD 10,000-15,000 savings
|
| 38 |
+
family: Solo applicant
|
| 39 |
+
timeline: 6-12 months
|
| 40 |
+
goals: >
|
| 41 |
+
I want to study in Europe on a modest budget and care about
|
| 42 |
+
post-study work options. Compare realistic countries, tuition and
|
| 43 |
+
living costs, student visa rules, and mark viable destinations on
|
| 44 |
+
the globe.
|
| 45 |
+
|
| 46 |
+
- id: brazil_remote_family
|
| 47 |
+
label: Remote worker family
|
| 48 |
+
profile:
|
| 49 |
+
citizenship:
|
| 50 |
+
- Brazil
|
| 51 |
+
current_country: Brazil
|
| 52 |
+
residence_status: Citizen
|
| 53 |
+
education: Bachelor's degree
|
| 54 |
+
occupation: Design / creative / media
|
| 55 |
+
experience: 3-5 years
|
| 56 |
+
languages:
|
| 57 |
+
- Portuguese
|
| 58 |
+
- English
|
| 59 |
+
budget: Monthly income USD 3,500-5,000
|
| 60 |
+
family: Spouse / partner + 1 child
|
| 61 |
+
timeline: 3-6 months
|
| 62 |
+
goals: >
|
| 63 |
+
We want a safe country with good schools and a route that does not
|
| 64 |
+
require a local job offer immediately. Compare digital-nomad,
|
| 65 |
+
investor, and family-friendly residency options with realistic
|
| 66 |
+
timelines under one year.
|
| 67 |
+
|
| 68 |
+
- id: nigeria_healthcare_worker
|
| 69 |
+
label: Nigeria healthcare worker
|
| 70 |
+
profile:
|
| 71 |
+
citizenship:
|
| 72 |
+
- Nigeria
|
| 73 |
+
current_country: Nigeria
|
| 74 |
+
residence_status: Citizen
|
| 75 |
+
education: Bachelor's degree
|
| 76 |
+
occupation: Nursing / caregiving
|
| 77 |
+
experience: 7-10 years
|
| 78 |
+
languages:
|
| 79 |
+
- English
|
| 80 |
+
budget: USD 15,000-25,000 savings
|
| 81 |
+
family: Spouse / civil partner only
|
| 82 |
+
timeline: 12-18 months
|
| 83 |
+
goals: >
|
| 84 |
+
I am a registered nurse looking for skilled-worker or health-sector
|
| 85 |
+
migration routes to Canada, the UK, or Australia. Compare licensing
|
| 86 |
+
steps, language tests, credential recognition, and which pathway is
|
| 87 |
+
most realistic for my profile.
|
| 88 |
+
|
| 89 |
+
- id: philippines_caregiver
|
| 90 |
+
label: Philippines caregiver
|
| 91 |
+
profile:
|
| 92 |
+
citizenship:
|
| 93 |
+
- Philippines
|
| 94 |
+
current_country: Philippines
|
| 95 |
+
residence_status: Citizen
|
| 96 |
+
education: Vocational / trade certificate
|
| 97 |
+
occupation: Nursing / caregiving
|
| 98 |
+
experience: 3-5 years
|
| 99 |
+
languages:
|
| 100 |
+
- English
|
| 101 |
+
- Filipino / Tagalog
|
| 102 |
+
budget: USD 5,000-10,000 savings
|
| 103 |
+
family: Solo applicant
|
| 104 |
+
timeline: 6-12 months
|
| 105 |
+
goals: >
|
| 106 |
+
I have caregiver experience and want to work abroad in Canada, Japan,
|
| 107 |
+
or Europe. Compare employer-sponsored routes, language requirements,
|
| 108 |
+
training or certification gaps, and total upfront costs.
|
| 109 |
+
|
| 110 |
+
- id: us_tech_europe
|
| 111 |
+
label: US tech worker exploring Europe
|
| 112 |
+
profile:
|
| 113 |
+
citizenship:
|
| 114 |
+
- United States
|
| 115 |
+
current_country: United States
|
| 116 |
+
residence_status: Citizen
|
| 117 |
+
education: Bachelor's degree
|
| 118 |
+
occupation: Software / IT
|
| 119 |
+
experience: 10-15 years
|
| 120 |
+
languages:
|
| 121 |
+
- English
|
| 122 |
+
budget: USD 60,000-100,000 savings
|
| 123 |
+
family: Spouse / civil partner only
|
| 124 |
+
timeline: 2-3 years
|
| 125 |
+
goals: >
|
| 126 |
+
My spouse and I want to move to Europe for quality of life without
|
| 127 |
+
giving up remote-friendly tech work immediately. Compare EU Blue
|
| 128 |
+
Card, freelancer/self-employed, and digital-nomad options in Portugal,
|
| 129 |
+
Germany, Spain, and the Netherlands.
|
ui/intake/choices.py
CHANGED
|
@@ -3,139 +3,19 @@ from __future__ import annotations
|
|
| 3 |
|
| 4 |
from functools import lru_cache
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
"Malaysia",
|
| 20 |
-
"Mexico",
|
| 21 |
-
"Netherlands",
|
| 22 |
-
"New Zealand",
|
| 23 |
-
"Nigeria",
|
| 24 |
-
"Philippines",
|
| 25 |
-
"Poland",
|
| 26 |
-
"Portugal",
|
| 27 |
-
"Singapore",
|
| 28 |
-
"South Africa",
|
| 29 |
-
"South Korea",
|
| 30 |
-
"Spain",
|
| 31 |
-
"Sweden",
|
| 32 |
-
"Switzerland",
|
| 33 |
-
"Taiwan",
|
| 34 |
-
"Thailand",
|
| 35 |
-
"United Arab Emirates",
|
| 36 |
-
"United Kingdom",
|
| 37 |
-
"United States",
|
| 38 |
-
"Vietnam",
|
| 39 |
-
]
|
| 40 |
-
|
| 41 |
-
EDUCATION_CHOICES = [
|
| 42 |
-
"High school / secondary",
|
| 43 |
-
"Associate degree",
|
| 44 |
-
"Bachelor's degree",
|
| 45 |
-
"Master's degree",
|
| 46 |
-
"PhD / doctorate",
|
| 47 |
-
"Professional degree (MD, JD, etc.)",
|
| 48 |
-
"Vocational / trade certificate",
|
| 49 |
-
"Currently studying",
|
| 50 |
-
]
|
| 51 |
-
|
| 52 |
-
OCCUPATION_CHOICES = [
|
| 53 |
-
"Software / IT",
|
| 54 |
-
"Engineering (non-software)",
|
| 55 |
-
"Healthcare",
|
| 56 |
-
"Education / teaching",
|
| 57 |
-
"Finance / accounting",
|
| 58 |
-
"Sales / marketing",
|
| 59 |
-
"Design / creative",
|
| 60 |
-
"Trades / skilled labor",
|
| 61 |
-
"Management / executive",
|
| 62 |
-
"Research / academia",
|
| 63 |
-
"Student / no full-time work",
|
| 64 |
-
"Self-employed / freelancer",
|
| 65 |
-
]
|
| 66 |
-
|
| 67 |
-
EXPERIENCE_CHOICES = [
|
| 68 |
-
"Less than 1 year",
|
| 69 |
-
"1-3 years",
|
| 70 |
-
"3-5 years",
|
| 71 |
-
"5-10 years",
|
| 72 |
-
"10+ years",
|
| 73 |
-
]
|
| 74 |
-
|
| 75 |
-
LANGUAGE_CHOICES = [
|
| 76 |
-
"Arabic",
|
| 77 |
-
"Bengali",
|
| 78 |
-
"Dutch",
|
| 79 |
-
"English",
|
| 80 |
-
"French",
|
| 81 |
-
"German",
|
| 82 |
-
"Hindi",
|
| 83 |
-
"Indonesian",
|
| 84 |
-
"Italian",
|
| 85 |
-
"Japanese",
|
| 86 |
-
"Korean",
|
| 87 |
-
"Mandarin Chinese",
|
| 88 |
-
"Polish",
|
| 89 |
-
"Portuguese",
|
| 90 |
-
"Russian",
|
| 91 |
-
"Spanish",
|
| 92 |
-
"Tagalog",
|
| 93 |
-
"Thai",
|
| 94 |
-
"Turkish",
|
| 95 |
-
"Urdu",
|
| 96 |
-
"Vietnamese",
|
| 97 |
-
]
|
| 98 |
-
|
| 99 |
-
BUDGET_CHOICES = [
|
| 100 |
-
"Under USD 5,000 savings",
|
| 101 |
-
"USD 5,000-15,000 savings",
|
| 102 |
-
"USD 15,000-30,000 savings",
|
| 103 |
-
"USD 30,000-50,000 savings",
|
| 104 |
-
"USD 50,000+ savings",
|
| 105 |
-
"Monthly income under USD 2,000",
|
| 106 |
-
"Monthly income USD 2,000-5,000",
|
| 107 |
-
"Monthly income USD 5,000+",
|
| 108 |
-
"Prefer lower cost of living",
|
| 109 |
-
"Flexible / not sure",
|
| 110 |
-
]
|
| 111 |
-
|
| 112 |
-
FAMILY_CHOICES = [
|
| 113 |
-
"Solo applicant",
|
| 114 |
-
"Spouse / partner only",
|
| 115 |
-
"Spouse + 1 child",
|
| 116 |
-
"Spouse + 2+ children",
|
| 117 |
-
"Dependents only (no spouse)",
|
| 118 |
-
"Extended family relocating together",
|
| 119 |
-
]
|
| 120 |
-
|
| 121 |
-
TIMELINE_CHOICES = [
|
| 122 |
-
"ASAP (under 6 months)",
|
| 123 |
-
"6-12 months",
|
| 124 |
-
"12-18 months",
|
| 125 |
-
"2-3 years",
|
| 126 |
-
"Long term / flexible",
|
| 127 |
-
"Exploring options only",
|
| 128 |
-
]
|
| 129 |
-
|
| 130 |
-
RESIDENCE_STATUS_CHOICES = [
|
| 131 |
-
"Citizen",
|
| 132 |
-
"Permanent resident",
|
| 133 |
-
"Work visa / employment pass",
|
| 134 |
-
"Student visa",
|
| 135 |
-
"Dependent / family visa",
|
| 136 |
-
"Tourist / short-term stay",
|
| 137 |
-
"Between visas / relocating soon",
|
| 138 |
-
]
|
| 139 |
|
| 140 |
|
| 141 |
@lru_cache(maxsize=1)
|
|
|
|
| 3 |
|
| 4 |
from functools import lru_cache
|
| 5 |
|
| 6 |
+
from ui.intake.loader import load_intake_choices
|
| 7 |
+
|
| 8 |
+
_choices = load_intake_choices()
|
| 9 |
+
|
| 10 |
+
FALLBACK_COUNTRIES = _choices["fallback_countries"]
|
| 11 |
+
EDUCATION_CHOICES = _choices["education"]
|
| 12 |
+
OCCUPATION_CHOICES = _choices["occupation"]
|
| 13 |
+
EXPERIENCE_CHOICES = _choices["experience"]
|
| 14 |
+
LANGUAGE_CHOICES = _choices["languages"]
|
| 15 |
+
BUDGET_CHOICES = _choices["budget"]
|
| 16 |
+
FAMILY_CHOICES = _choices["family"]
|
| 17 |
+
TIMELINE_CHOICES = _choices["timeline"]
|
| 18 |
+
RESIDENCE_STATUS_CHOICES = _choices["residence_status"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
|
| 21 |
@lru_cache(maxsize=1)
|
ui/intake/examples.py
CHANGED
|
@@ -1,25 +1,47 @@
|
|
| 1 |
# ui/intake/examples.py
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# ui/intake/examples.py
|
| 2 |
+
from __future__ import annotations
|
| 3 |
+
|
| 4 |
+
from typing import Any, TypedDict
|
| 5 |
+
|
| 6 |
+
from ui.intake.loader import load_demo_personas
|
| 7 |
+
from ui.intake.prompts import build_profile_prompt
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class PersonaProfile(TypedDict):
|
| 11 |
+
citizenship: list[str] | str
|
| 12 |
+
current_country: str
|
| 13 |
+
residence_status: str
|
| 14 |
+
education: str
|
| 15 |
+
occupation: str
|
| 16 |
+
experience: str
|
| 17 |
+
languages: list[str] | str
|
| 18 |
+
budget: str
|
| 19 |
+
family: str
|
| 20 |
+
timeline: str
|
| 21 |
+
goals: str
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class DemoPersona(TypedDict):
|
| 25 |
+
id: str
|
| 26 |
+
label: str
|
| 27 |
+
profile: PersonaProfile
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def demo_personas() -> list[DemoPersona]:
|
| 31 |
+
return load_demo_personas() # type: ignore[return-value]
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def persona_prompt(profile: PersonaProfile | dict[str, Any]) -> dict[str, object]:
|
| 35 |
+
return build_profile_prompt(
|
| 36 |
+
profile.get("citizenship"),
|
| 37 |
+
profile.get("current_country"),
|
| 38 |
+
profile.get("residence_status"),
|
| 39 |
+
profile.get("education"),
|
| 40 |
+
profile.get("occupation"),
|
| 41 |
+
profile.get("experience"),
|
| 42 |
+
profile.get("languages"),
|
| 43 |
+
profile.get("budget"),
|
| 44 |
+
profile.get("family"),
|
| 45 |
+
profile.get("timeline"),
|
| 46 |
+
profile.get("goals", ""),
|
| 47 |
+
)
|
ui/intake/loader.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ui/intake/loader.py
|
| 2 |
+
from __future__ import annotations
|
| 3 |
+
|
| 4 |
+
from functools import lru_cache
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
from typing import Any
|
| 7 |
+
|
| 8 |
+
import yaml
|
| 9 |
+
|
| 10 |
+
DATA_DIR = Path(__file__).resolve().parents[2] / "data" / "intake"
|
| 11 |
+
CHOICES_DIR = DATA_DIR / "choices"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@lru_cache(maxsize=1)
|
| 15 |
+
def load_intake_choices() -> dict[str, list[str]]:
|
| 16 |
+
choices: dict[str, list[str]] = {}
|
| 17 |
+
for path in sorted(CHOICES_DIR.glob("*.yaml")):
|
| 18 |
+
with path.open(encoding="utf-8") as handle:
|
| 19 |
+
data = yaml.safe_load(handle)
|
| 20 |
+
if not isinstance(data, list):
|
| 21 |
+
raise ValueError(f"{path.name} must contain a YAML list")
|
| 22 |
+
choices[path.stem] = list(data)
|
| 23 |
+
return choices
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
@lru_cache(maxsize=1)
|
| 27 |
+
def load_demo_personas() -> list[dict[str, Any]]:
|
| 28 |
+
with (DATA_DIR / "personas.yaml").open(encoding="utf-8") as handle:
|
| 29 |
+
data = yaml.safe_load(handle)
|
| 30 |
+
return list(data["personas"])
|
ui/intake/panel.py
CHANGED
|
@@ -12,6 +12,7 @@ from ui.intake.choices import (
|
|
| 12 |
TIMELINE_CHOICES,
|
| 13 |
country_choices,
|
| 14 |
)
|
|
|
|
| 15 |
from ui.intake.prompts import build_profile_prompt
|
| 16 |
|
| 17 |
|
|
|
|
| 12 |
TIMELINE_CHOICES,
|
| 13 |
country_choices,
|
| 14 |
)
|
| 15 |
+
from ui.intake.examples import demo_personas, persona_prompt
|
| 16 |
from ui.intake.prompts import build_profile_prompt
|
| 17 |
|
| 18 |
|