diff --git a/wab/.eslintrc.cjs b/wab/.eslintrc.cjs
new file mode 100644
index 000000000..d6c953795
--- /dev/null
+++ b/wab/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/wab/.gitignore b/wab/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/wab/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/wab/137f588a-3ab4-43c8-8678-8b5ee0288bd3.zip b/wab/137f588a-3ab4-43c8-8678-8b5ee0288bd3.zip
new file mode 100644
index 000000000..0fe243627
Binary files /dev/null and b/wab/137f588a-3ab4-43c8-8678-8b5ee0288bd3.zip differ
diff --git a/wab/README.md b/wab/README.md
new file mode 100644
index 000000000..5c898bfd5
--- /dev/null
+++ b/wab/README.md
@@ -0,0 +1,8 @@
+# Magic Patterns - Vite Template
+
+This code was generated by [Magic Patterns](https://magicpatterns.com) for this design: [Source Design](https://www.magicpatterns.com/c/n8t6ftyeqwzmbvhlpr27qb)
+
+## Getting Started
+
+1. Run `npm install`
+2. Run `npm run dev`
diff --git a/wab/index.html b/wab/index.html
new file mode 100644
index 000000000..3073c4c15
--- /dev/null
+++ b/wab/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Cambodia Immigration Portal - Fork - Fork - Fork
+
+
+
+
+
+
diff --git a/wab/package.json b/wab/package.json
new file mode 100644
index 000000000..b0e952906
--- /dev/null
+++ b/wab/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "magic-patterns-vite-template",
+ "version": "0.0.1",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "npx vite",
+ "build": "npx vite build",
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
+ "preview": "npx vite preview"
+ },
+ "dependencies": {
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "@emotion/react": "^11.13.3",
+ "lucide-react": "0.522.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.18",
+ "@types/react": "^18.3.1",
+ "@types/react-dom": "^18.3.1",
+ "@typescript-eslint/eslint-plugin": "^5.54.0",
+ "@typescript-eslint/parser": "^5.54.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "eslint": "^8.50.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.1",
+ "typescript": "^5.5.4",
+ "vite": "^5.2.0",
+ "tailwindcss": "3.4.17",
+ "autoprefixer": "latest",
+ "postcss": "latest"
+ }
+}
\ No newline at end of file
diff --git a/wab/postcss.config.js b/wab/postcss.config.js
new file mode 100644
index 000000000..2e7af2b7f
--- /dev/null
+++ b/wab/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/wab/public/image-1.png b/wab/public/image-1.png
new file mode 100644
index 000000000..2b302fa63
Binary files /dev/null and b/wab/public/image-1.png differ
diff --git a/wab/public/image-2.png b/wab/public/image-2.png
new file mode 100644
index 000000000..9cd7f94de
Binary files /dev/null and b/wab/public/image-2.png differ
diff --git a/wab/public/image-3.png b/wab/public/image-3.png
new file mode 100644
index 000000000..1510a90b2
Binary files /dev/null and b/wab/public/image-3.png differ
diff --git a/wab/public/image-4.png b/wab/public/image-4.png
new file mode 100644
index 000000000..788a6b39e
Binary files /dev/null and b/wab/public/image-4.png differ
diff --git a/wab/public/image.png b/wab/public/image.png
new file mode 100644
index 000000000..153053b74
Binary files /dev/null and b/wab/public/image.png differ
diff --git a/wab/public/logo-new.png b/wab/public/logo-new.png
new file mode 100644
index 000000000..8b0603a45
Binary files /dev/null and b/wab/public/logo-new.png differ
diff --git a/wab/src/App.tsx b/wab/src/App.tsx
new file mode 100644
index 000000000..5002216e8
--- /dev/null
+++ b/wab/src/App.tsx
@@ -0,0 +1,67 @@
+import React, { useState } from 'react';
+import { GovernmentBar } from './components/GovernmentBar';
+import { Header } from './components/Header';
+import { AnnouncementBanner } from './components/AnnouncementBanner';
+import { FeaturedNewsSection } from './components/FeaturedNewsSection';
+import { ServiceCards } from './components/ServiceCards';
+import { SmartGateSection } from './components/SmartGateSection';
+import { NewsSection } from './components/NewsSection';
+import { Footer } from './components/Footer';
+import { LoginOverlay } from './pages/LoginPage';
+import { DashboardPage } from './pages/DashboardPage';
+import { ComplaintFormPage } from './pages/ComplaintFormPage';
+import { QuestionFormPage } from './pages/QuestionFormPage';
+import { LanguageProvider } from './lib/LanguageContext';
+function AppContent() {
+ const [showLogin, setShowLogin] = useState(true);
+ const [currentPage, setCurrentPage] = useState<
+ 'home' | 'dashboard' | 'complaint' | 'question'>(
+ 'home');
+ const handleGuestLogin = () => {
+ setCurrentPage('dashboard');
+ setShowLogin(false);
+ };
+ if (currentPage === 'complaint') {
+ return setCurrentPage('dashboard')} />;
+ }
+ if (currentPage === 'question') {
+ return setCurrentPage('dashboard')} />;
+ }
+ if (currentPage === 'dashboard') {
+ return (
+ setCurrentPage('complaint')}
+ onNavigateToQuestion={() => setCurrentPage('question')} />);
+
+
+ }
+ return (
+
+
setShowLogin(true)} />
+ setShowLogin(true)} />
+
+
+
+
+
+
+
+
+
+ {/* Login Overlay */}
+ {showLogin &&
+ setShowLogin(false)}
+ onGuestLogin={handleGuestLogin} />
+
+ }
+ );
+
+}
+export function App() {
+ return (
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/wab/src/components/AnnouncementBanner.tsx b/wab/src/components/AnnouncementBanner.tsx
new file mode 100644
index 000000000..84962ddbb
--- /dev/null
+++ b/wab/src/components/AnnouncementBanner.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import { ChevronRight } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function AnnouncementBanner() {
+ const { t } = useLanguage();
+ return (
+ );
+
+}
\ No newline at end of file
diff --git a/wab/src/components/FeaturedNewsSection.tsx b/wab/src/components/FeaturedNewsSection.tsx
new file mode 100644
index 000000000..f740fb5d0
--- /dev/null
+++ b/wab/src/components/FeaturedNewsSection.tsx
@@ -0,0 +1,248 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { ChevronLeft, ChevronRight } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function FeaturedNewsSection() {
+ const { t } = useLanguage();
+ const [currentSlide, setCurrentSlide] = useState(0);
+ const [isTransitioning, setIsTransitioning] = useState(false);
+ const slides = [
+ {
+ id: 1,
+ image: "/image.png",
+
+ title:
+ 'ប្រជុំពិភាក្សាការងារពាក់ព័ន្ធប្រព័ន្ធម៉ែហានិភ័យអ្នកដំណើរតាមផ្លូវអាកាស GTAS',
+ description:
+ 'ប្រជុំពិភាក្សាការងារពាក់ព័ន្ធប្រព័ន្ធម៉ែហានិភ័យអ្នកដំណើរតាមផ្លូវអាកាស GTAS',
+ date: 'នៅព្រឹកថ្ងៃប្រហស្បតិ៍ ទី៨ ខែមករា ឆ្នាំ២០២៦ នេះ ឯកឧត្តម ឧត្តមសេនីយ៍ឯក សុខ វាសនា អគ្គនាយកអន្តោប្រវេសន៍...'
+ },
+ {
+ id: 2,
+ image: "/image-1.png",
+
+ title:
+ 'កិច្ចប្រជុំតាមដានខ្មែរនភាពការងារបង្រ្គាបបទល្មើសជោគជ័យតាមប្រព័ន្ធបច្ចេកវិទ្យា...',
+ description:
+ 'កិច្ចប្រជុំតាមដានខ្មែរនភាពការងារបង្រ្គាបបទល្មើសជោគជ័យតាមប្រព័ន្ធបច្ចេកវិទ្យា (Online Scams)',
+ date: 'នៅព្រឹកថ្ងៃអង្គារ ទី៦ ខែមករា ឆ្នាំ២០២៦ នេះ ឯកឧត្តម ឧត្តមសេនីយ៍ឯក សុខ វាសនា អគ្គនាយកអន្តោប្រវេសន៍...'
+ },
+ {
+ id: 3,
+ image: "/image-2.png",
+
+ title:
+ 'ពិធីបិទព្រឹត្តិការណ៍ប្រកួតកីឡាមហាបាដន់ ពានរង្វាន់ឯកឧត្តមអគ្គសេនីយ៍ឯក ស សុខា...',
+ description:
+ 'ពិធីបិទព្រឹត្តិការណ៍ប្រកួតកីឡាមហាបាដន់ ពានរង្វាន់ឯកឧត្តមអគ្គសេនីយ៍ឯក ស សុខា ដើម្បីអបអរសាទរវិជ្ជមានមួយ ពាមករា',
+ date: 'នៅសៀលថ្ងៃចន្ទ ទី៥ ខែមករា ឆ្នាំ២០២៦ នេះ ឯកឧត្តម ឧត្តមសេនីយ៍ឯក សុខ វាសនា អគ្គ...'
+ },
+ {
+ id: 4,
+ image: "/image-3.png",
+
+ title:
+ 'វឌ្ឍនភាពការងារត្រួតពិនិត្យវត្តមានស្នាក់នៅរបស់ជនបរទេសនៅក្នុងព្រះរាជាណាចក្រ...',
+ description:
+ 'វឌ្ឍនភាពការងារត្រួតពិនិត្យវត្តមានស្នាក់នៅរបស់ជនបរទេសនៅក្នុងព្រះរាជាណាចក្រកម្ពុជា',
+ date: 'នៅព្រឹកថ្ងៃសុក្រ ទី៩ ខែមករា ឆ្នាំ២០២៦ នេះ ឯកឧត្តម ឧត្តមសេនីយ៍ឯក សុខ វាសនា អគ្គនាយកអន្តោប្រវេសន៍ ព្រមទាំង...'
+ }];
+
+ const goToSlide = useCallback(
+ (index: number) => {
+ if (isTransitioning) return;
+ setIsTransitioning(true);
+ setCurrentSlide(index);
+ setTimeout(() => setIsTransitioning(false), 600);
+ },
+ [isTransitioning]
+ );
+ const nextSlide = useCallback(() => {
+ goToSlide((currentSlide + 1) % slides.length);
+ }, [currentSlide, slides.length, goToSlide]);
+ const prevSlide = useCallback(() => {
+ goToSlide((currentSlide - 1 + slides.length) % slides.length);
+ }, [currentSlide, slides.length, goToSlide]);
+ // Auto-rotate every 3 seconds
+ useEffect(() => {
+ const timer = setInterval(() => {
+ nextSlide();
+ }, 3000);
+ return () => clearInterval(timer);
+ }, [nextSlide]);
+ return (
+
+
+
+ {/* Left Column: News Carousel */}
+
+ {/* All slides stacked, only current one visible */}
+ {slides.map((slide, idx) =>
+
+ )}
+
+ {/* Content Overlay */}
+
+
+
+ {slides[currentSlide].title}
+
+
+ {slides[currentSlide].description}
+
+
+ {slides[currentSlide].date}
+
+
+
+ {/* Navigation Arrows */}
+
+
+
+
+
+
+
+
+
+ {/* Pagination Dots */}
+
+ {slides.map((_, idx) =>
+ goToSlide(idx)}
+ className={`h-2.5 rounded-full transition-all duration-300 ${currentSlide === idx ? 'bg-white w-8' : 'bg-white/40 w-2.5 hover:bg-white/70'}`} />
+
+ )}
+
+
+ {/* Progress Bar */}
+
+
+
+ {/* Right Column: Profile Card */}
+
+ {/* Orange Header Curve */}
+
+
+
+ {/* Profile Image */}
+
+
+
+
+
+
+
+ {/* Text Content */}
+
+
+ សារស្វាគមន៍របស់ឯកឧត្តម
+
+
+ ឯកឧត្តម ឧត្តមសេនីយ៍ឯក សុខ វាសនា
+
+
+
+ សូមស្វាគមន៍ចំពោះការចូលទស្សនាគេហទំព័រអគ្គនាយកដ្ឋាន អន្តោប្រវេសន៍!
+ អ្នកអានជាទីគោរ! ដើម្បីឆ្លើតទៅសម្រេចបានកម្មវត្ថុស័យឆ្នាំ២០៤០
+ ដែលកម្ពុជាជាយផ្សេទមានចំណុលខ្ពស់ រជ្ជកាលបានដាក់ចេញនូវក្រុម
+ ខណ្ឌនយោបាយ យុទ្ធសាស្រ្តបញ្ញាពេលណ ដំណាក់កាលទី១...
+
+
+
+
+ Read More
+
+
+
+ {/* Background Pattern (Subtle) */}
+
+
+
+
+
+
+ {/* Orange Announcement Banner - Ticker */}
+
+
+
+ {/* Label Tag */}
+
+
+ ព័ត៌មានថ្មី
+
+
+ {/* Scrolling Ticker */}
+
+
+
+
+ នៅក្នុងឆ្នាំ២០២៦ចាប់ពីខែកុម្ភះនេះទៅថ្នាក់ដឹងនាំនៃព្រះរាជាណាចក្រកម្ពុជាបានចេញសេចក្តីថ្លែងការណ័នឹងជំរាប់ដល់ជនជាតិបរទេសទាំងអស់ដែលរស់នៅកម្ពុជា
+ ដែលមានប្រវត្តរស់នៅកម្ពុជា២ឆ្នាំឡើងនិងមានសិទ្ធិស្នើរសុំចូលជាសញ្ជាត្តិកម្ពុជា
+ ៕ ពត៏មានបន្ថែមអាចទំនាក់ទំនងមកកាន់គេហទំព័រផ្លូវការរបស់
+ អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍ ។
+
+
+ នៅក្នុងឆ្នាំ២០២៦ចាប់ពីខែកុម្ភះនេះទៅថ្នាក់ដឹងនាំនៃព្រះរាជាណាចក្រកម្ពុជាបានចេញសេចក្តីថ្លែងការណ័នឹងជំរាប់ដល់ជនជាតិបរទេសទាំងអស់ដែលរស់នៅកម្ពុជា
+ ដែលមានប្រវត្តរស់នៅកម្ពុជា២ឆ្នាំឡើងនិងមានសិទ្ធិស្នើរសុំចូលជាសញ្ជាត្តិកម្ពុជា
+ ៕ ពត៏មានបន្ថែមអាចទំនាក់ទំនងមកកាន់គេហទំព័រផ្លូវការរបស់
+ អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍ ។
+
+
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/wab/src/components/Footer.tsx b/wab/src/components/Footer.tsx
new file mode 100644
index 000000000..85e571eb0
--- /dev/null
+++ b/wab/src/components/Footer.tsx
@@ -0,0 +1,115 @@
+import React from 'react';
+import { MapPin, Phone, Mail, Facebook, Twitter, Youtube, Globe } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function Footer() {
+ const {
+ t
+ } = useLanguage();
+ return
+
+
+ {/* Column 1: About */}
+
+
+
+
+
+ {t('department_name').split(' ').slice(0, 2).join(' ')}
+
+ {t('department_name').split(' ').slice(2).join(' ')}
+
+
+
+
+ {t('footer_desc')}
+
+
+
+
+ {/* Column 2: Quick Links */}
+
+
+ {t('quick_links')}
+
+
+ {[t('nav_about'), t('service_visa_title'), t('nav_legal'), t('nav_services'), t('nav_news'), t('nav_contact')].map((item) =>
+
+
+ {item}
+
+ )}
+
+
+
+ {/* Column 3: Services */}
+
+
+ {t('e_services')}
+
+
+ {['e-Visa Application', 'Foreigners Present in Cambodia System', 'Non-Immigrant Visa Extension', 'Exit Visa', 'Refugee Travel Document'].map((item) =>
+
+
+ {item}
+
+ )}
+
+
+
+ {/* Column 4: Contact */}
+
+
+ {t('contact_info')}
+
+
+
+
+
+ No. 322, Russian Federation Blvd,
+ Phnom Penh, Cambodia
+
+
+
+
+ +855 23 890 380
+
+
+
+ info@immigration.gov.kh
+
+
+
+ www.immigration.gov.kh
+
+
+
+
+
+ {/* Bottom Bar */}
+
+
{t('copyright_kh')}
+
+
+
+ ;
+}
\ No newline at end of file
diff --git a/wab/src/components/GovernmentBar.tsx b/wab/src/components/GovernmentBar.tsx
new file mode 100644
index 000000000..ed5bc91de
--- /dev/null
+++ b/wab/src/components/GovernmentBar.tsx
@@ -0,0 +1,125 @@
+import React, { useState } from 'react';
+import { ChevronDown, Globe, User, Check } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+import { Language } from '../lib/translations';
+interface GovernmentBarProps {
+ onLoginClick?: () => void;
+}
+export function GovernmentBar({ onLoginClick }: GovernmentBarProps) {
+ const { language, setLanguage, t } = useLanguage();
+ const [isLangMenuOpen, setIsLangMenuOpen] = useState(false);
+ const languages: {
+ code: Language;
+ label: string;
+ flag: string;
+ }[] = [
+ {
+ code: 'en',
+ label: 'English',
+ flag: '🇬🇧'
+ },
+ {
+ code: 'km',
+ label: 'ភាសាខ្មែរ',
+ flag: '🇰🇭'
+ },
+ {
+ code: 'zh',
+ label: '中文',
+ flag: 'https://firebasestorage.googleapis.com/v0/b/egdi-ecosystem.appspot.com/o/eligibleNationalities%2Fchina.png?alt=media&token=094e6a2b-6af6-430d-9f51-5c74b70882e8'
+ }];
+
+ const currentLang = languages.find((l) => l.code === language) || languages[0];
+ return (
+
+
+
+
+
+
+ {t('official_website')}
+
+
+ Official Gov Portal
+
+
+
+
setIsLangMenuOpen(!isLangMenuOpen)}
+ className="flex items-center gap-1 text-[10px] md:text-xs text-white/90 hover:text-[#feb335] transition-colors px-2 py-0.5 rounded hover:bg-white/10">
+
+
+ {currentLang.flag.startsWith('http') ?
+ :
+
+
+ currentLang.flag
+ }
+
+ {currentLang.label}
+
+
+
+
+ {isLangMenuOpen &&
+ <>
+
setIsLangMenuOpen(false)}>
+
+
+ {languages.map((lang) =>
+
{
+ setLanguage(lang.code);
+ setIsLangMenuOpen(false);
+ }}
+ className={`w-full text-left px-3 py-2 text-xs flex items-center justify-between hover:bg-gray-50 ${language === lang.code ? 'text-[#feb335] font-medium bg-gray-50' : 'text-gray-700'}`}>
+
+
+
+ {lang.flag.startsWith('http') ?
+ :
+
+
+ lang.flag
+ }
+
+
{lang.label}
+
+ {language === lang.code && }
+
+ )}
+
+ >
+ }
+
+
+
+
+
+
+ {t('sign_in')}
+
+
+
);
+
+}
\ No newline at end of file
diff --git a/wab/src/components/Header.tsx b/wab/src/components/Header.tsx
new file mode 100644
index 000000000..32bbb5b6d
--- /dev/null
+++ b/wab/src/components/Header.tsx
@@ -0,0 +1,419 @@
+import React, { useState } from 'react';
+import { Menu, X, User, ChevronRight, ChevronDown, Check } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+import { Language } from '../lib/translations';
+interface HeaderProps {
+ onLoginClick?: () => void;
+}
+export function Header({ onLoginClick }: HeaderProps) {
+ const { t, language, setLanguage } = useLanguage();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const [expandedMobileMenu, setExpandedMobileMenu] = useState(
+ null
+ );
+ const [isLangMenuOpen, setIsLangMenuOpen] = useState(false);
+ const languages: {
+ code: Language;
+ label: string;
+ flag: string;
+ }[] = [
+ {
+ code: 'en',
+ label: 'English',
+ flag: '🇬🇧'
+ },
+ {
+ code: 'km',
+ label: 'ភាសាខ្មែរ',
+ flag: '🇰🇭'
+ },
+ {
+ code: 'zh',
+ label: '中文',
+ flag: 'https://firebasestorage.googleapis.com/v0/b/egdi-ecosystem.appspot.com/o/eligibleNationalities%2Fchina.png?alt=media&token=094e6a2b-6af6-430d-9f51-5c74b70882e8'
+ }];
+
+ const currentLang = languages.find((l) => l.code === language) || languages[0];
+ const navItems = [
+ {
+ label: t('nav_home'),
+ href: '/',
+ active: true
+ },
+ {
+ label: t('nav_about'),
+ href: '#',
+ active: false,
+ children: [
+ {
+ label: t('about_dg_message'),
+ href: '#'
+ },
+ {
+ label: t('about_general_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_infrastructure'),
+ href: '#'
+ },
+ {
+ label: t('about_leaders'),
+ href: '#'
+ },
+ {
+ label: t('about_admin_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_non_immigrant_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_immigrant_refugee_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_immigrant_investor_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_gateway_1'),
+ href: '#'
+ },
+ {
+ label: t('about_gateway_2'),
+ href: '#'
+ },
+ {
+ label: t('about_investigation_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_it_dept'),
+ href: '#'
+ },
+ {
+ label: t('about_uyfc'),
+ href: '#'
+ },
+ {
+ label: t('about_gender'),
+ href: '#'
+ },
+ {
+ label: t('about_sport'),
+ href: '#'
+ }]
+
+ },
+ {
+ label: t('nav_services'),
+ href: '#',
+ active: false,
+ children: [
+ {
+ label: t('service_visa_extension'),
+ href: '#'
+ },
+ {
+ label: t('service_residence_permit'),
+ href: '#'
+ },
+ {
+ label: t('service_foreign_passport'),
+ href: '#'
+ },
+ {
+ label: t('service_citizenship'),
+ href: '#'
+ },
+ {
+ label: t('nav_contact'),
+ href: '#'
+ }]
+
+ },
+ {
+ label: t('nav_news'),
+ href: '/news',
+ active: false
+ },
+ {
+ label: t('nav_digital_library'),
+ href: '#',
+ active: false,
+ children: [
+ {
+ label: t('digital_announcement'),
+ href: '#'
+ },
+ {
+ label: t('digital_official_doc'),
+ href: '#'
+ }]
+
+ }];
+
+ const toggleMobileSubmenu = (label: string) => {
+ if (expandedMobileMenu === label) {
+ setExpandedMobileMenu(null);
+ } else {
+ setExpandedMobileMenu(label);
+ }
+ };
+ return (
+
+
+ {/* Overlay for better text readability */}
+
+
+
+ {/* Top Branding Area */}
+
+
+
+
+
+
+
+
+ អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍
+
+
+
+ General Department of Immigration
+
+
+
+
+
+ setIsMenuOpen(!isMenuOpen)}
+ aria-label="Toggle menu">
+
+ {isMenuOpen ?
+ :
+
+
+ }
+
+
+
+
+
+ {/* Scrolling Marquee Ticker */}
+
+
+ {/* Desktop Navigation Bar */}
+
+
+
+
+
+
+
+
+ {/* Language Selector */}
+
+
setIsLangMenuOpen(!isLangMenuOpen)}
+ className="flex items-center gap-2 text-sm text-white hover:text-[#feb335] transition-colors py-2">
+
+
+ {isLangMenuOpen &&
+
+ {languages.map((lang) =>
+
{
+ setLanguage(lang.code);
+ setIsLangMenuOpen(false);
+ }}
+ className={`w-full text-left px-4 py-2.5 text-sm flex items-center justify-between hover:bg-gray-50 ${language === lang.code ? 'text-[#83255c] font-medium bg-gray-50' : 'text-gray-700'}`}>
+
+
+
+ {lang.flag.startsWith('http') ?
+ :
+
+
+ lang.flag
+ }
+
+
{lang.label}
+
+ {language === lang.code &&
+
+ }
+
+ )}
+
+ }
+
+
+
+
+
+ {/* Mobile Navigation Dropdown */}
+ {isMenuOpen &&
+
+
+
+ {navItems.map((item) =>
+
+
+ {item.children ?
+
+
toggleMobileSubmenu(item.label)}
+ className={`w-full flex items-center justify-between px-4 py-3 rounded-lg transition-colors ${item.active || expandedMobileMenu === item.label ? 'text-[#feb335] font-medium' : 'text-white/90 hover:bg-white/5 hover:text-[#feb335]'}`}>
+
+ {item.label}
+
+
+
+
+ {expandedMobileMenu === item.label &&
+
+ }
+
:
+
+ setIsMenuOpen(false)}>
+
+ {item.label}
+ {item.active && }
+
+ }
+
+ )}
+
+ {/* Mobile Language Selector */}
+
+
+ Language
+
+
+ {languages.map((lang) =>
+
setLanguage(lang.code)}
+ className={`flex flex-col items-center justify-center p-2 rounded-lg border ${language === lang.code ? 'bg-[#feb335]/20 border-[#feb335] text-[#feb335]' : 'border-white/10 text-white/70 hover:bg-white/5'}`}>
+
+
+ {lang.flag.startsWith('http') ?
+ :
+
+
+ lang.flag
+ }
+
+ {lang.label}
+
+ )}
+
+
+
+
+ {
+ if (onLoginClick) onLoginClick();
+ setIsMenuOpen(false);
+ }}
+ className="w-full flex items-center gap-3 px-4 py-3 text-white/90 hover:bg-white/5 hover:text-[#feb335] rounded-lg transition-colors text-left">
+
+
+ {t('sign_in')}
+
+
+
+
+
+ }
+ );
+
+}
\ No newline at end of file
diff --git a/wab/src/components/HeroSection.tsx b/wab/src/components/HeroSection.tsx
new file mode 100644
index 000000000..568093be6
--- /dev/null
+++ b/wab/src/components/HeroSection.tsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import { ArrowRight, ChevronRight } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function HeroSection() {
+ const {
+ t
+ } = useLanguage();
+ return
+ {/* Background Image Placeholder with Gradient */}
+
+ {/* Abstract shapes to simulate Angkor Wat silhouette */}
+
+
+
+
+ {/* Overlay Gradient */}
+
+
+ {/* Content */}
+
+
+
+
+
+ {t('hero_official_portal')}
+
+
+
+
+ {t('hero_welcome')}
+
+ {t('hero_immigration_services')}
+
+
+
+
+ {t('hero_description')}
+
+
+
+
+ {t('hero_apply_visa')}
+
+
+
+ {t('hero_check_status')}
+
+
+
+
+
+
+ {/* Bottom decorative bar */}
+
+ ;
+}
\ No newline at end of file
diff --git a/wab/src/components/NewsSection.tsx b/wab/src/components/NewsSection.tsx
new file mode 100644
index 000000000..de2888be5
--- /dev/null
+++ b/wab/src/components/NewsSection.tsx
@@ -0,0 +1,80 @@
+import React from 'react';
+import { Calendar, ArrowRight, Tag } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function NewsSection() {
+ const {
+ t
+ } = useLanguage();
+ const news = [{
+ id: 1,
+ title: 'New Visa Regulations for 2024 Announced',
+ date: 'October 15, 2023',
+ category: 'Policy',
+ excerpt: 'The General Department of Immigration has released updated guidelines for long-term visa extensions effective from January 1st.',
+ image: 'bg-[#1B2A4A]/10'
+ }, {
+ id: 2,
+ title: 'Smart Gate Expansion at Phnom Penh International Airport',
+ date: 'September 28, 2023',
+ category: 'Technology',
+ excerpt: 'Ten additional automated border control gates have been installed to facilitate faster processing for eligible travelers.',
+ image: 'bg-[#D4841C]/10'
+ }, {
+ id: 3,
+ title: 'Department Launches New Online Service Portal',
+ date: 'September 10, 2023',
+ category: 'Service',
+ excerpt: 'Citizens and foreigners can now access 15 different immigration services through the newly upgraded digital platform.',
+ image: 'bg-gray-200'
+ }];
+ return
+
+
+
+
+ {news.map((item) =>
+ {/* Image Placeholder */}
+
+
+ News Image
+
+
+
+ {item.category}
+
+
+
+
+ )}
+
+
+ ;
+}
\ No newline at end of file
diff --git a/wab/src/components/ServiceCards.tsx b/wab/src/components/ServiceCards.tsx
new file mode 100644
index 000000000..8c2c8c8c4
--- /dev/null
+++ b/wab/src/components/ServiceCards.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import { FileText, Smartphone, Briefcase, AlertTriangle, Plane, Phone, ArrowRight, UserPlus } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+export function ServiceCards() {
+ const {
+ t
+ } = useLanguage();
+ const services = [{
+ title: t('service_visa_title'),
+ description: t('service_visa_desc'),
+ icon: FileText,
+ link: '#'
+ }, {
+ title: t('service_smartgate_title'),
+ description: t('service_smartgate_desc'),
+ icon: Smartphone,
+ link: '#'
+ }, {
+ title: t('service_work_title'),
+ description: t('service_work_desc'),
+ icon: Briefcase,
+ link: '#'
+ }, {
+ title: t('service_citizenship_title'),
+ description: t('service_citizenship_desc'),
+ icon: UserPlus,
+ link: '#'
+ }, {
+ title: t('service_advisory_title'),
+ description: t('service_advisory_desc'),
+ icon: AlertTriangle,
+ link: '#'
+ }, {
+ title: t('service_arrival_title'),
+ description: t('service_arrival_desc'),
+ icon: Plane,
+ link: '#'
+ }, {
+ title: t('service_contact_title'),
+ description: t('service_contact_desc'),
+ icon: Phone,
+ link: '#'
+ }];
+ return
+
+
+
+ {t('services_title')}
+
+
+
{t('services_subtitle')}
+
+
+
+
+ ;
+}
\ No newline at end of file
diff --git a/wab/src/components/SmartGateSection.tsx b/wab/src/components/SmartGateSection.tsx
new file mode 100644
index 000000000..1d3799925
--- /dev/null
+++ b/wab/src/components/SmartGateSection.tsx
@@ -0,0 +1,188 @@
+import React from 'react';
+import { CheckCircle2 } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+type Region = 'ASEAN' | 'Asia' | 'Americas' | 'Oceania' | 'Europe';
+type Country = {
+ name: string;
+ flag: string;
+};
+const countryData: Record = {
+ ASEAN: [
+ {
+ name: 'Cambodia',
+ flag: '🇰🇭'
+ },
+ {
+ name: 'Indonesia',
+ flag: '🇮🇩'
+ },
+ {
+ name: 'Malaysia',
+ flag: '🇲🇾'
+ },
+ {
+ name: 'Singapore',
+ flag: '🇸🇬'
+ },
+ {
+ name: 'Laos',
+ flag: '🇱🇦'
+ },
+ {
+ name: 'Philippines',
+ flag: '🇵🇭'
+ },
+ {
+ name: 'Vietnam',
+ flag: '🇻🇳'
+ },
+ {
+ name: 'Thailand',
+ flag: '🇹🇭'
+ },
+ {
+ name: 'Myanmar',
+ flag: '🇲🇲'
+ },
+ {
+ name: 'Brunei Darussalam',
+ flag: '🇧🇳'
+ }],
+
+ Asia: [
+ {
+ name: 'China',
+ flag: '🇨🇳'
+ },
+ {
+ name: 'Japan',
+ flag: '🇯🇵'
+ },
+ {
+ name: 'Macao SAR',
+ flag: '🇲🇴'
+ },
+ {
+ name: 'Republic of Korea (South Korea)',
+ flag: '🇰🇷'
+ },
+ {
+ name: 'Hong Kong SAR',
+ flag: '🇭🇰'
+ }],
+
+ Americas: [
+ {
+ name: 'USA',
+ flag: '🇺🇸'
+ }],
+
+ Oceania: [
+ {
+ name: 'Australia',
+ flag: '🇦🇺'
+ }],
+
+ Europe: [
+ {
+ name: 'France',
+ flag: '🇫🇷'
+ },
+ {
+ name: 'Germany',
+ flag: '🇩🇪'
+ },
+ {
+ name: 'United Kingdom',
+ flag: '🇬🇧'
+ }]
+
+};
+export function SmartGateSection() {
+ const { t } = useLanguage();
+ const getRegionName = (region: Region) => {
+ switch (region) {
+ case 'ASEAN':
+ return t('region_asean');
+ case 'Asia':
+ return t('region_asia');
+ case 'Americas':
+ return t('region_americas');
+ case 'Oceania':
+ return t('region_oceania');
+ case 'Europe':
+ return t('region_europe');
+ default:
+ return region;
+ }
+ };
+ const RegionBlock = ({
+ region,
+ className = ''
+
+
+
+ }: {region: Region;className?: string;}) =>
+
+
+ {getRegionName(region)}
+
+
+ {countryData[region].map((country) =>
+
+
+
+
+ {country.flag}
+
+
+ {country.name}
+
+
+ )}
+
+
;
+
+ return (
+
+
+ {/* Header */}
+
+
+ {t('smartgate_title')}
+
+
+
+ {/* Content Wrapper */}
+
+ {/* Top Row: ASEAN + Asia */}
+
+ {/* ASEAN takes 2/3 width on large screens */}
+
+
+ {/* Asia takes 1/3 width on large screens */}
+
+
+
+ {/* Bottom Row: Americas + Oceania + Europe */}
+
+
+
+
+
+
+ {/* Footer Note */}
+
+
+ {t('smartgate_requirement')}
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/wab/src/index.css b/wab/src/index.css
new file mode 100644
index 000000000..809a753f9
--- /dev/null
+++ b/wab/src/index.css
@@ -0,0 +1,20 @@
+/* URL IMPORTS (SUCH AS FONT IMPORTS) SHOULD BE KEPT ABOVE TAILWIND IMPORTS - DO NOT DELETE THIS COMMENT */
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Moul&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Battambang:wght@300;400;700&display=swap');
+
+/* PLEASE NOTE: THESE TAILWIND IMPORTS SHOULD NEVER BE DELETED - DO NOT DELETE THIS COMMENT */
+@import 'tailwindcss/base';
+@import 'tailwindcss/components';
+@import 'tailwindcss/utilities';
+
+/* DO NOT DELETE THESE TAILWIND IMPORTS, OTHERWISE THE STYLING WILL NOT RENDER AT ALL - DO NOT DELETE THIS COMMENT */
+
+@keyframes marquee {
+ 0% {
+ transform: translateX(0%);
+ }
+ 100% {
+ transform: translateX(-50%);
+ }
+}
diff --git a/wab/src/index.tsx b/wab/src/index.tsx
new file mode 100644
index 000000000..bdf8733fb
--- /dev/null
+++ b/wab/src/index.tsx
@@ -0,0 +1,6 @@
+import './index.css';
+import "./index.css";
+import React from "react";
+import { render } from "react-dom";
+import { App } from "./App";
+render( , document.getElementById("root"));
\ No newline at end of file
diff --git a/wab/src/lib/LanguageContext.tsx b/wab/src/lib/LanguageContext.tsx
new file mode 100644
index 000000000..f5d962c28
--- /dev/null
+++ b/wab/src/lib/LanguageContext.tsx
@@ -0,0 +1,37 @@
+import React, { useState, createContext, useContext } from 'react';
+import { translations, Language } from './translations';
+interface LanguageContextType {
+ language: Language;
+ setLanguage: (lang: Language) => void;
+ t: (key: keyof typeof translations) => string;
+}
+const LanguageContext = createContext(undefined);
+export function LanguageProvider({
+ children
+
+
+}: {children: ReactNode;}) {
+ const [language, setLanguage] = useState('km');
+ const t = (key: keyof typeof translations) => {
+ const translation = translations[key];
+ if (!translation) {
+ console.warn(`Translation key "${key}" not found.`);
+ return key;
+ }
+ return translation[language] || translation['en'];
+ };
+ return
+ {children}
+ ;
+}
+export function useLanguage() {
+ const context = useContext(LanguageContext);
+ if (context === undefined) {
+ throw new Error('useLanguage must be used within a LanguageProvider');
+ }
+ return context;
+}
\ No newline at end of file
diff --git a/wab/src/lib/translations.ts b/wab/src/lib/translations.ts
new file mode 100644
index 000000000..a756243cd
--- /dev/null
+++ b/wab/src/lib/translations.ts
@@ -0,0 +1,442 @@
+export type Language = 'en' | 'km' | 'zh';
+
+export const translations = {
+ // Common
+ official_website: {
+ en: 'An official website of the Kingdom of Cambodia',
+ km: 'គេហទំព័រផ្លូវការនៃព្រះរាជាណាចក្រកម្ពុជា',
+ zh: '柬埔寨王国官方网站'
+ },
+ sign_in: {
+ en: 'Sign In',
+ km: 'ចូលគណនី',
+ zh: '登录'
+ },
+ department_name: {
+ en: 'General Department of Immigration',
+ km: 'អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍',
+ zh: '移民总局'
+ },
+
+ // Navigation
+ nav_home: {
+ en: 'Home',
+ km: 'ទំព័រដើម',
+ zh: '首页'
+ },
+ nav_services: {
+ en: 'Services',
+ km: 'សេវាកម្ម',
+ zh: '服务'
+ },
+ nav_news: {
+ en: 'News',
+ km: 'ព័ត៌មាន',
+ zh: '新闻'
+ },
+ nav_legal: {
+ en: 'Legal Documents',
+ km: 'ឯកសារផ្លូវច្បាប់',
+ zh: '法律文件'
+ },
+ nav_about: {
+ en: 'About Us',
+ km: 'អំពីយើង',
+ zh: '关于我们'
+ },
+ nav_contact: {
+ en: 'Contact Us',
+ km: 'ទំនាក់ទំនង',
+ zh: '联系我们'
+ },
+ nav_digital_library: {
+ en: 'Digital Library',
+ km: 'បណ្ណាល័យឌីជីថល',
+ zh: '数字图书馆'
+ },
+
+ // About Dropdown
+ about_dg_message: {
+ en: "Director General's Welcome Message",
+ km: 'សារស្វាគមន៍របស់អគ្គនាយក',
+ zh: '总干事致辞'
+ },
+ about_general_dept: {
+ en: 'General Department',
+ km: 'អគ្គនាយកដ្ឋាន',
+ zh: '总局'
+ },
+ about_infrastructure: {
+ en: 'Structure',
+ km: 'រចនាសម្ព័ន្ធ',
+ zh: '组织结构'
+ },
+ about_leaders: {
+ en: 'Leaders',
+ km: 'ថ្នាក់ដឹកនាំ',
+ zh: '领导层'
+ },
+ about_admin_dept: {
+ en: 'General Administration Dept',
+ km: 'នាយកដ្ឋានរដ្ឋបាលសរុប',
+ zh: '综合行政部'
+ },
+ about_non_immigrant_dept: {
+ en: 'Non-Immigrant Foreign Dept',
+ km: 'នាយកដ្ឋានជនបរទេសមិនមែនអន្តោប្រវេសន្ត',
+ zh: '非移民外国人管理部'
+ },
+ about_immigrant_refugee_dept: {
+ en: 'Immigrant & Refugee Dept',
+ km: 'នាយកដ្ឋានជនបរទេសអន្តោប្រវេសន្ត និងជនភៀសខ្លួន',
+ zh: '移民与难民部'
+ },
+ about_immigrant_investor_dept: {
+ en: 'Immigrant & Private Investor Dept',
+ km: 'នាយកដ្ឋានជនបរទេសអន្តោប្រវេសន្តនិងជាអ្នកវិនិយោគឯកជន',
+ zh: '移民与私人投资者部'
+ },
+ about_gateway_1: {
+ en: 'Gateway Dept 1',
+ km: 'នាយកដ្ឋានច្រកទ្វារទី១',
+ zh: '第一口岸部'
+ },
+ about_gateway_2: {
+ en: 'Gateway Dept 2',
+ km: 'នាយកដ្ឋានច្រកទ្វារទី២',
+ zh: '第二口岸部'
+ },
+ about_investigation_dept: {
+ en: 'Investigation & Procedure Dept',
+ km: 'នាយកដ្ឋានស៊ើបអង្កេត និងអនុវត្តនិតិវិធី',
+ zh: '调查与程序执行部'
+ },
+ about_it_dept: {
+ en: 'IT Dept',
+ km: 'នាយកដ្ឋានបច្ចេកវិទ្យាព័ត៌មានអន្តោប្រវេសន៍',
+ zh: '移民信息技术部'
+ },
+ about_uyfc: {
+ en: 'Union of Youth Federations of Cambodia',
+ km: 'សហភាពសហព័ន្ធយុវជនកម្ពុជា',
+ zh: '柬埔寨青年联合会'
+ },
+ about_gender: {
+ en: 'Gender',
+ km: 'យេនឌ័រ',
+ zh: '性别事务'
+ },
+ about_sport: {
+ en: 'Sport',
+ km: 'កីឡា',
+ zh: '体育'
+ },
+
+ // Services Dropdown
+ service_visa_extension: {
+ en: 'VISAS AND EXTENSIONS',
+ km: 'ទិដ្ឋាការ និងការបន្តសុពលភាព',
+ zh: '签证与延期'
+ },
+ service_residence_permit: {
+ en: 'RESIDENCE PERMIT',
+ km: 'ប័ណ្ណស្នាក់នៅ',
+ zh: '居留许可'
+ },
+ service_foreign_passport: {
+ en: 'FOREIGN PASSPORT SERVICES',
+ km: 'សេវាធ្វើលិខិតឆ្លងដែនជនបរទេស',
+ zh: '外籍办理护照'
+ },
+ service_citizenship: {
+ en: 'CAMBODIAN CITIZENSHIP APPLICATION',
+ km: 'ពាក្យសុំសញ្ជាតិខ្មែរសម្រាប់ជនបរទេស',
+ zh: '外籍申请加入柬埔寨国籍'
+ },
+
+ // Digital Library Dropdown
+ digital_announcement: {
+ en: 'Announcement',
+ km: 'សេចក្តីប្រកាស',
+ zh: '公告'
+ },
+ digital_official_doc: {
+ en: 'Official Document',
+ km: 'ឯកសារផ្លូវការ',
+ zh: '官方文件'
+ },
+
+ // Announcement Banner
+ banner_earrival: {
+ en: 'All travelers can submit the Cambodia e-Arrival within 7 days before or on arrival.',
+ km: 'អ្នកធ្វើដំណើរទាំងអស់អាចដាក់ Cambodia e-Arrival ក្នុងរយៈពេល ៧ ថ្ងៃមុនពេលមកដល់ ឬនៅពេលមកដល់។',
+ zh: '所有旅客可在抵达前7天内或抵达时提交柬埔寨电子入境卡。'
+ },
+ banner_submission_free: {
+ en: 'Submission is Free.',
+ km: 'ការដាក់ពាក្យគឺឥតគិតថ្លៃ។',
+ zh: '提交免费。'
+ },
+
+ // Hero Section
+ hero_official_portal: {
+ en: 'Official Government Portal',
+ km: 'ច្រកទ្វាររដ្ឋាភិបាលផ្លូវការ',
+ zh: '官方政府门户'
+ },
+ hero_welcome: {
+ en: 'Welcome to Cambodia',
+ km: 'សូមស្វាគមន៍មកកាន់កម្ពុជា',
+ zh: '欢迎来到柬埔寨'
+ },
+ hero_immigration_services: {
+ en: 'Immigration Services',
+ km: 'សេវាអន្តោប្រវេសន៍',
+ zh: '移民服务'
+ },
+ hero_description: {
+ en: 'Facilitating safe travel, managing immigration, and serving the Kingdom with integrity and efficiency.',
+ km: 'សម្របសម្រួលការធ្វើដំណើរប្រកបដោយសុវត្ថិភាព គ្រប់គ្រងអន្តោប្រវេសន៍ និងបម្រើព្រះរាជាណាចក្រដោយសុចរិតភាព និងប្រសិទ្ធភាព។',
+ zh: '促进安全旅行,管理移民事务,以诚信和高效服务王国。'
+ },
+ hero_apply_visa: {
+ en: 'Apply for Visa',
+ km: 'ស្នើសុំទិដ្ឋាការ',
+ zh: '申请签证'
+ },
+ hero_check_status: {
+ en: 'Check Status',
+ km: 'ពិនិត្យស្ថានភាព',
+ zh: '检查状态'
+ },
+
+ // Service Cards
+ services_title: {
+ en: 'Our Services',
+ km: 'សេវាកម្មរបស់យើង',
+ zh: '我们的服务'
+ },
+ services_subtitle: {
+ en: 'Access essential immigration services quickly and efficiently through our digital platforms.',
+ km: 'ចូលប្រើសេវាកម្មអន្តោប្រវេសន៍សំខាន់ៗយ៉ាងឆាប់រហ័ស និងប្រកបដោយប្រសិទ្ធភាពតាមរយៈវេទិកាឌីជីថលរបស់យើង។',
+ zh: '通过我们的数字平台快速高效地访问基本移民服务。'
+ },
+ service_visa_title: {
+ en: 'Visa Application',
+ km: 'ពាក្យសុំទិដ្ឋាការ',
+ zh: '签证申请'
+ },
+ service_visa_desc: {
+ en: 'Apply for tourist, business, and other visa types online securely.',
+ km: 'ដាក់ពាក្យសុំទិដ្ឋាការទេសចរណ៍ អាជីវកម្ម និងប្រភេទផ្សេងៗទៀតតាមអ៊ីនធឺណិតដោយសុវត្ថិភាព។',
+ zh: '在线安全申请旅游、商务和其他类型的签证。'
+ },
+ service_smartgate_title: {
+ en: 'Smart Gate',
+ km: 'ច្រកទ្វារឆ្លាតវៃ',
+ zh: '智能闸门'
+ },
+ service_smartgate_desc: {
+ en: 'Automated border control system for eligible passport holders.',
+ km: 'ប្រព័ន្ធត្រួតពិនិត្យព្រំដែនដោយស្វ័យប្រវត្តិសម្រាប់អ្នកកាន់លិខិតឆ្លងដែនដែលមានសិទ្ធិ។',
+ zh: '适用于符合条件的护照持有者的自动边境控制系统。'
+ },
+ service_work_title: {
+ en: 'Work Permits',
+ km: 'ប័ណ្ណការងារ',
+ zh: '工作许可证'
+ },
+ service_work_desc: {
+ en: 'Information and application process for foreign employment.',
+ km: 'ព័ត៌មាន និងដំណើរការដាក់ពាក្យសម្រាប់ការងារបរទេស។',
+ zh: '外国就业的信息和申请流程。'
+ },
+ service_advisory_title: {
+ en: 'Travel Advisory',
+ km: 'ការណែនាំអំពីការធ្វើដំណើរ',
+ zh: '旅行建议'
+ },
+ service_advisory_desc: {
+ en: 'Latest updates on travel restrictions and entry requirements.',
+ km: 'បច្ចុប្បន្នភាពចុងក្រោយស្តីពីការរឹតបន្តឹងការធ្វើដំណើរ និងតម្រូវការចូល។',
+ zh: '关于旅行限制和入境要求的最新更新。'
+ },
+ service_arrival_title: {
+ en: 'e-Arrival',
+ km: 'e-Arrival',
+ zh: '电子入境卡'
+ },
+ service_arrival_desc: {
+ en: 'Submit your arrival card digitally before you fly.',
+ km: 'ដាក់ជូនប័ណ្ណមកដល់របស់អ្នកតាមប្រព័ន្ធឌីជីថលមុនពេលអ្នកហោះហើរ។',
+ zh: '在飞行前以数字方式提交您的入境卡。'
+ },
+ service_contact_title: {
+ en: 'Contact Us',
+ km: 'ទាក់ទងមកពួកយើង',
+ zh: '联系我们'
+ },
+ service_contact_desc: {
+ en: 'Get in touch with our support team for assistance.',
+ km: 'ទាក់ទងក្រុមគាំទ្ររបស់យើងសម្រាប់ជំនួយ។',
+ zh: '与我们的支持团队联系以获得帮助。'
+ },
+ service_citizenship_title: {
+ en: 'Citizenship Application',
+ km: 'ពាក្យសុំសញ្ជាតិខ្មែរ',
+ zh: '申请加入柬埔寨国籍'
+ },
+ service_citizenship_desc: {
+ en: 'Foreign nationals can apply for Cambodian citizenship through the official naturalization process.',
+ km: 'ជនបរទេសអាចដាក់ពាក្យសុំសញ្ជាតិខ្មែរតាមរយៈដំណើរការផ្លូវការនៃការចូលសញ្ជាតិ។',
+ zh: '外籍人士可通过官方入籍程序申请加入柬埔寨国籍。'
+ },
+ access_service: {
+ en: 'Access Service',
+ km: 'ចូលប្រើសេវាកម្ម',
+ zh: '访问服务'
+ },
+
+ // Smart Gate Section
+ smartgate_label: {
+ en: 'Automated Border Control',
+ km: 'ការត្រួតពិនិត្យព្រំដែនដោយស្វ័យប្រវត្តិ',
+ zh: '自动边境控制'
+ },
+ smartgate_title: {
+ en: 'Eligible Passports For Smart Gate At Techo International Airport (KTI)',
+ km: 'លិខិតឆ្លងដែនដែលមានសិទ្ធិសម្រាប់ច្រកទ្វារឆ្លាតវៃនៅអាកាសយានដ្ឋានអន្តរជាតិតេជោ (KTI)',
+ zh: '德崇国际机场 (KTI) 智能闸门适用护照'
+ },
+ smartgate_desc: {
+ en: 'Citizens of the following countries can use the automated Smart Gates for faster immigration clearance.',
+ km: 'ពលរដ្ឋនៃប្រទេសខាងក្រោមអាចប្រើប្រាស់ច្រកទ្វារឆ្លាតវៃដោយស្វ័យប្រវត្តិសម្រាប់ការត្រួតពិនិត្យអន្តោប្រវេសន៍លឿនជាងមុន។',
+ zh: '以下国家的公民可以使用自动智能闸门进行更快的移民通关。'
+ },
+ region_asean: {
+ en: 'ASEAN',
+ km: 'អាស៊ាន',
+ zh: '东盟'
+ },
+ region_asia: {
+ en: 'Asia',
+ km: 'អាស៊ី',
+ zh: '亚洲'
+ },
+ region_americas: {
+ en: 'Americas',
+ km: 'អាមេរិក',
+ zh: '美洲'
+ },
+ region_oceania: {
+ en: 'Oceania',
+ km: 'អូសេអានី',
+ zh: '大洋洲'
+ },
+ region_europe: {
+ en: 'Europe',
+ km: 'អឺរ៉ុប',
+ zh: '欧洲'
+ },
+ smartgate_requirement: {
+ en: 'Valid e-Passport required for Smart Gate usage',
+ km: 'តម្រូវឱ្យមានលិខិតឆ្លងដែនអេឡិចត្រូនិកដែលមានសុពលភាពសម្រាប់ការប្រើប្រាស់ច្រកទ្វារឆ្លាតវៃ',
+ zh: '使用智能闸门需要有效的电子护照'
+ },
+
+ // News Section
+ news_title: {
+ en: 'Latest News & Updates',
+ km: 'ព័ត៌មាន & បច្ចុប្បន្នភាពចុងក្រោយ',
+ zh: '最新新闻与动态'
+ },
+ news_subtitle: {
+ en: 'Stay informed about immigration policies and announcements.',
+ km: 'ទទួលបានព័ត៌មានអំពីគោលនយោបាយអន្តោប្រវេសន៍ និងសេចក្តីប្រកាស។',
+ zh: '随时了解移民政策和公告。'
+ },
+ view_all_news: {
+ en: 'View All News',
+ km: 'មើលព័ត៌មានទាំងអស់',
+ zh: '查看所有新闻'
+ },
+ read_full_article: {
+ en: 'Read Full Article',
+ km: 'អានអត្ថបទពេញ',
+ zh: '阅读全文'
+ },
+
+ // Footer
+ footer_desc: {
+ en: 'The General Department of Immigration is responsible for managing the flow of foreign nationals entering and exiting the Kingdom of Cambodia.',
+ km: 'អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍ទទួលខុសត្រូវក្នុងការគ្រប់គ្រងលំហូរជនបរទេសដែលចូល និងចេញពីព្រះរាជាណាចក្រកម្ពុជា។',
+ zh: '移民总局负责管理进出柬埔寨王国的外国国民流动。'
+ },
+ quick_links: {
+ en: 'Quick Links',
+ km: 'តំណភ្ជាប់រហ័ស',
+ zh: '快速链接'
+ },
+ e_services: {
+ en: 'E-Services',
+ km: 'សេវាអេឡិចត្រូនិក',
+ zh: '电子服务'
+ },
+ contact_info: {
+ en: 'Contact Info',
+ km: 'ព័ត៌មានទំនាក់ទំនង',
+ zh: '联系信息'
+ },
+ rights_reserved: {
+ en: 'All Rights Reserved.',
+ km: 'រក្សាសិទ្ធិគ្រប់យ៉ាង។',
+ zh: '保留所有权利。'
+ },
+ privacy_policy: {
+ en: 'Privacy Policy',
+ km: 'គោលការណ៍ភាពឯកជន',
+ zh: '隐私政策'
+ },
+ terms_of_use: {
+ en: 'Terms of Use',
+ km: 'លក្ខខណ្ឌនៃការប្រើប្រាស់',
+ zh: '使用条款'
+ },
+ sitemap: {
+ en: 'Sitemap',
+ km: 'ផែនទីគេហទំព័រ',
+ zh: '网站地图'
+ },
+
+ // Login
+ login_guest: {
+ en: 'Login as Guest',
+ km: 'ចូលដោយជាភ្ញៀវ',
+ zh: '以访客身份登录'
+ },
+ login_gmail: {
+ en: 'Login with Gmail',
+ km: 'ចូលជាមួយ Gmail',
+ zh: '使用 Gmail 登录'
+ },
+ copyright_kh: {
+ en: 'Copyright © 2024 Kingdom of Cambodia. All Rights Reserved.',
+ km: 'រក្សាសិទ្ធិ © 2024 ព្រះរាជាណាចក្រកម្ពុជា រក្សាសិទ្ធិគ្រប់យ៉ាង',
+ zh: '版权所有 © 2024 柬埔寨王国。保留所有权利。'
+ },
+ version: {
+ en: 'Version: 1.0.0',
+ km: 'ជំនាន់: 1.0.0',
+ zh: '版本: 1.0.0'
+ },
+ get_it_on: {
+ en: 'GET IT ON',
+ km: 'GET IT ON',
+ zh: '获取于'
+ },
+ download_on: {
+ en: 'Download on the',
+ km: 'Download on the',
+ zh: '下载于'
+ }
+};
\ No newline at end of file
diff --git a/wab/src/pages/ComplaintFormPage.tsx b/wab/src/pages/ComplaintFormPage.tsx
new file mode 100644
index 000000000..31fcc5464
--- /dev/null
+++ b/wab/src/pages/ComplaintFormPage.tsx
@@ -0,0 +1,278 @@
+import React from 'react';
+import {
+ X,
+ Grid3x3,
+ Bell,
+ User,
+ Bold,
+ Italic,
+ Underline,
+ Strikethrough,
+ List,
+ ListOrdered,
+ Type,
+ AlignLeft,
+ Paperclip,
+ ChevronDown } from
+'lucide-react';
+interface ComplaintFormPageProps {
+ onBack: () => void;
+}
+export function ComplaintFormPage({ onBack }: ComplaintFormPageProps) {
+ return (
+
+ {/* Top Header (Same as Dashboard) */}
+
+
+
+ HOTLINE
+
+
+
+
+
+
中文
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Sub-Header */}
+
+
+
+
+
+
+
新投诉
+
+
+ 发送反馈
+
+
+
+ {/* Main Content */}
+
+
+ {/* Form Header */}
+
+
投诉详情
+
+ 我们会优先考虑您的反馈和疑虑。
+
+ 请在下面的表格中填写您的请求或评论,然后单击"提交"。
+
+
+
+ {/* Section 1: Comments */}
+
+
1.评论
+
+ {/* Complaint Type */}
+
+
+
+
+
+ 选择评论类型*
+
+ 服务态度
+ 办理流程
+ 系统问题
+ 其他
+
+
+
+
+
+ {/* Rich Text Editor */}
+
+ {/* Toolbar */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+ {/* Text Area */}
+
+
+
+
+
+ {/* Attachment */}
+
+
+ 附件(如有)
+
+
+
+
+
+ 插入附件
+
+
+ 附件可以是图片、视频或其他文件(大小不得超过100MB)。
+
+
+
+
+
+
+ {/* Section 2: Personal Info */}
+
+
2.个人信息
+
+ {/* Name Fields */}
+
+
+ {/* Phone Number */}
+
+
+
+
+
+
+
+ 电话号码*
+
+
+
+
+ {/* Gender */}
+
+
+
+
+
+ 男
+ 女
+
+
+
+ 性别*
+
+
+
+
+
+ {/* Nationality */}
+
+
+
+
+
);
+
+}
\ No newline at end of file
diff --git a/wab/src/pages/DashboardPage.tsx b/wab/src/pages/DashboardPage.tsx
new file mode 100644
index 000000000..006788bff
--- /dev/null
+++ b/wab/src/pages/DashboardPage.tsx
@@ -0,0 +1,221 @@
+import React from 'react';
+import {
+ Search,
+ Plus,
+ Grid3x3,
+ Bell,
+ User,
+ MessageSquare,
+ HelpCircle,
+ Phone,
+ Facebook,
+ Mail,
+ Package } from
+'lucide-react';
+interface DashboardPageProps {
+ onNavigateToComplaint?: () => void;
+ onNavigateToQuestion?: () => void;
+}
+export function DashboardPage({
+ onNavigateToComplaint,
+ onNavigateToQuestion
+}: DashboardPageProps) {
+ return (
+
+ {/* Left Sidebar */}
+
+ {/* Logo Area */}
+
+
+
+
+ អគ្គនាយកដ្ឋានអន្តោប្រវេសន៍
+
+
+
+ {/* Search & Action */}
+
+
+ {/* Tabs */}
+
+
+ 评论
+
+
+ 问题与解答
+
+
+
+ {/* Filters */}
+
+
+
+
+ 全部
+
+
+
+ 草稿
+
+
+
+ 提交
+
+
+
+ 待办的
+
+
+
+
+
+ {/* Empty State */}
+
+
+
+ {/* Main Content */}
+
+ {/* Header */}
+
+
+
+ HOTLINE
+
+
+
+
+
+
中文
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Dashboard Content */}
+
+
+ {/* Card 1: Post Comment */}
+
+
+
+
+
+
+ 发表评论
+
+
+ 对于有关移民程序、系统或官员的任何问题,请提交正式投诉。
+
+
+
+ {/* Card 2: Have a Question */}
+
+
+
+
+
+
+ 有一个问题?
+
+
+ 如果您需要有关任何移民问题的澄清或帮助,请向我们提交问题。
+
+
+
+ {/* Card 3: Contact */}
+
+
+
+
+
);
+
+}
\ No newline at end of file
diff --git a/wab/src/pages/LoginPage.tsx b/wab/src/pages/LoginPage.tsx
new file mode 100644
index 000000000..7b1c773f0
--- /dev/null
+++ b/wab/src/pages/LoginPage.tsx
@@ -0,0 +1,112 @@
+import React from 'react';
+import { X } from 'lucide-react';
+import { useLanguage } from '../lib/LanguageContext';
+interface LoginOverlayProps {
+ onClose?: () => void;
+ onGuestLogin?: () => void;
+}
+export function LoginOverlay({
+ onClose,
+ onGuestLogin
+}: LoginOverlayProps) {
+ const {
+ t
+ } = useLanguage();
+ const handleGuestLogin = () => {
+ if (onGuestLogin) {
+ onGuestLogin();
+ } else if (onClose) {
+ onClose();
+ }
+ };
+ return
+ {/* Backdrop */}
+
+
+ {/* White Card */}
+
+ {/* Close Button */}
+
+
+
+
+ {/* Content */}
+
+ {/* Government Seal */}
+
+
+ {/* Khmer Title */}
+
+ {t('department_name')}
+
+
+ {/* Divider */}
+
+
+ {/* Buttons */}
+
+ {/* Guest Login Button */}
+
+ {t('login_guest')}
+
+
+ {/* Gmail Login Button */}
+
+
+
+
+
+
+
+ {t('login_gmail')}
+
+
+
+ {/* Copyright */}
+
+
{t('copyright_kh')}
+
{t('version')}
+
+
+ {/* App Store Badges */}
+
+
+
+
;
+}
\ No newline at end of file
diff --git a/wab/src/pages/QuestionFormPage.tsx b/wab/src/pages/QuestionFormPage.tsx
new file mode 100644
index 000000000..af19571d2
--- /dev/null
+++ b/wab/src/pages/QuestionFormPage.tsx
@@ -0,0 +1,286 @@
+import React from 'react';
+import {
+ X,
+ Grid3x3,
+ Bell,
+ User,
+ Bold,
+ Italic,
+ Underline,
+ Strikethrough,
+ List,
+ ListOrdered,
+ Type,
+ AlignLeft,
+ Paperclip,
+ ChevronDown } from
+'lucide-react';
+interface QuestionFormPageProps {
+ onBack: () => void;
+}
+export function QuestionFormPage({ onBack }: QuestionFormPageProps) {
+ return (
+
+ {/* Top Header */}
+
+
+
+ HOTLINE
+
+
+
+
+
中文
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Sub-Header */}
+
+
+
+
+
+
+
新问题
+
+
+
+ 发送反馈
+
+
+
+ {/* Main Content */}
+
+
+ {/* Form Header */}
+
+
+ 问题与解答
+
+
+ 在这里您可以找到过去提出的问题的答案。
+
+ 如果您的问题在常见问题解答中没有得到解答,请在下面创建一个问题。
+
+
+
+ {/* Section 1: Question */}
+
+
1.问题
+
+ {/* Question Type */}
+
+
+
+
+
+ 选择问题类型*
+
+ 签证问题
+ 护照问题
+ 居留许可
+ 其他
+
+
+
+
+
+ {/* Rich Text Editor */}
+
+
+ 问题*
+
+
+
+ {/* Toolbar */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+ {/* Text Area */}
+
+
+
+
+
+ {/* Attachment */}
+
+
+ 附件(如有)
+
+
+
+
+
+ 插入附件
+
+
+ 附件可以是图片、视频或其他文件(大小不得超过100MB)。
+
+
+
+
+
+
+ {/* Section 2: Personal Info */}
+
+
2.个人信息
+
+
+
+ {/* Phone Number */}
+
+
+
+
+
+
+
+ 电话号码*
+
+
+
+
+ {/* Gender */}
+
+
+
+
+
+ 男
+ 女
+
+
+
+ 性别*
+
+
+
+
+
+ {/* Nationality */}
+
+
+
+
+
);
+
+}
\ No newline at end of file
diff --git a/wab/tailwind.config.js b/wab/tailwind.config.js
new file mode 100644
index 000000000..2aab84e6c
--- /dev/null
+++ b/wab/tailwind.config.js
@@ -0,0 +1,71 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ './index.html',
+ './src/**/*.{js,ts,jsx,tsx}'
+],
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: ['Inter', 'Battambang', 'system-ui', 'sans-serif'],
+ khmer: ['Battambang', 'sans-serif'],
+ 'khmer-title': ['Moul', 'serif'],
+ },
+ colors: {
+ navy: {
+ 50: '#f2f5f9',
+ 100: '#e1e8f0',
+ 200: '#c5d3e3',
+ 300: '#9db5d0',
+ 400: '#7092ba',
+ 500: '#4d74a3',
+ 600: '#385a85',
+ 700: '#2d486b',
+ 800: '#1B2A4A', // Primary Navy (darker than 500 usually, but adjusting scale to fit)
+ 900: '#111a2e',
+ 950: '#0a0f1a',
+ },
+ // Adjusting the provided navy #1B2A4A to be the 900 or 800 level for better contrast text,
+ // but prompt asked for it as a base. Let's make a custom scale where 500 is the brand color.
+ brandNavy: {
+ 50: '#eff4ff',
+ 100: '#dbe6fe',
+ 200: '#bfd3fe',
+ 300: '#93bbfd',
+ 400: '#609afa',
+ 500: '#3b82f6', // standard blue
+ 600: '#2563eb',
+ 700: '#1d4ed8',
+ 800: '#1B2A4A', // The requested Navy
+ 900: '#17223b',
+ },
+ // Let's try a more manual scale centered on the requested colors
+ customNavy: {
+ 50: '#f4f6f8',
+ 100: '#e4e8ed',
+ 200: '#cdd5df',
+ 300: '#aab9cc',
+ 400: '#8098b6',
+ 500: '#5e7a9e',
+ 600: '#466082',
+ 700: '#364b68',
+ 800: '#1B2A4A', // Using this as the deep primary
+ 900: '#16223b',
+ },
+ gold: {
+ 50: '#fbf8f3',
+ 100: '#f5efe4',
+ 200: '#ebdcc3',
+ 300: '#dfc29a',
+ 400: '#D4841C', // The requested Gold
+ 500: '#b56f16',
+ 600: '#8f5610',
+ 700: '#6b400c',
+ 800: '#4a2c08',
+ 900: '#2b1904',
+ }
+ }
+ },
+ },
+ plugins: [],
+}
\ No newline at end of file
diff --git a/wab/tsconfig.json b/wab/tsconfig.json
new file mode 100644
index 000000000..a7fc6fbf2
--- /dev/null
+++ b/wab/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/wab/tsconfig.node.json b/wab/tsconfig.node.json
new file mode 100644
index 000000000..97ede7ee6
--- /dev/null
+++ b/wab/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/wab/vite.config.ts b/wab/vite.config.ts
new file mode 100644
index 000000000..5a33944a9
--- /dev/null
+++ b/wab/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})