diff --git a/apps/36-blocks/src/app/app.component.ts b/apps/36-blocks/src/app/app.component.ts index c59fa7b3..fcd9bdd2 100644 --- a/apps/36-blocks/src/app/app.component.ts +++ b/apps/36-blocks/src/app/app.component.ts @@ -118,16 +118,22 @@ export class AppComponent extends BaseComponent implements OnInit, OnDestroy { if (isPlatformBrowser(this.platformId)) { this.actions$.pipe(ofType(logInActions.authenticatedAction), takeUntil(this.destroy$)).subscribe(() => { const currentUrl = this.router.url; + const websiteRoutes = [ + '/pricing', + '/about', + '/contact', + '/security', + '/privacy', + '/terms', + '/register', + '/login', + ]; const isOnWebsiteRoute = currentUrl === '/' || currentUrl === '' || - currentUrl.startsWith('/pricing') || - currentUrl.startsWith('/about') || - currentUrl.startsWith('/contact') || - currentUrl.startsWith('/security') || - currentUrl.startsWith('/privacy') || - currentUrl.startsWith('/terms'); - if (isOnWebsiteRoute) { + websiteRoutes.some((route) => currentUrl.startsWith(route)); + const isOnboardingRoute = currentUrl.startsWith('/onboarding'); + if (isOnWebsiteRoute && !isOnboardingRoute) { this.router.navigate(['/app/dashboard']); } }); diff --git a/apps/36-blocks/src/app/app.config.ts b/apps/36-blocks/src/app/app.config.ts index 8a254d25..7960b13b 100644 --- a/apps/36-blocks/src/app/app.config.ts +++ b/apps/36-blocks/src/app/app.config.ts @@ -15,8 +15,10 @@ import { appRoutes } from './app.routes'; import { environment } from '../environments/environment'; import { reducers, clearStateMetaReducer } from './core/ngrx/store/app.state'; import { loginsReducer } from './website/home/ngrx/store/login.state'; +import { registrationReducer } from './website/home/ngrx/reducers/registration.reducer'; import { RootEffects } from './core/ngrx/effects/root'; import { LogInEffects } from './website/home/ngrx/effects/login.effects'; +import { RegistrationEffects } from './website/home/ngrx/effects/registration.effects'; import { ErrorInterceptor } from '@proxy/services/interceptor/errorInterceptor'; import { ProxyBaseUrls } from '@proxy/models/root-models'; import { AuthInitializerService } from './core/auth-initializer.service'; @@ -33,7 +35,8 @@ export const appConfig: ApplicationConfig = { provideHttpClient(withFetch(), withInterceptorsFromDi()), provideStore(reducers, { metaReducers: [clearStateMetaReducer] }), provideState('auth', loginsReducer), - provideEffects([RootEffects, LogInEffects]), + provideState('registration', registrationReducer), + provideEffects([RootEffects, LogInEffects, RegistrationEffects]), ...(!environment.production ? [provideStoreDevtools({ maxAge: 25, serialize: true })] : []), { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, { diff --git a/apps/36-blocks/src/app/app.routes.ts b/apps/36-blocks/src/app/app.routes.ts index c167936d..da6cd867 100644 --- a/apps/36-blocks/src/app/app.routes.ts +++ b/apps/36-blocks/src/app/app.routes.ts @@ -1,19 +1,21 @@ import { Component, inject } from '@angular/core'; import { Route, Router } from '@angular/router'; -import { AngularFireAuthGuard, redirectUnauthorizedTo } from '@angular/fire/compat/auth-guard'; import { CookieService } from 'ngx-cookie-service'; import { AuthService } from '@proxy/services/proxy/auth'; +import { CanActivateRouteGuard } from './website/home/authguard'; @Component({ template: '', standalone: true }) class NotFoundRedirectComponent {} -const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['login']); - export const appRoutes: Route[] = [ { path: '', loadChildren: () => import('./website/website.routes').then((r) => r.websiteRoutes), }, + { + path: 'onboarding', + loadComponent: () => import('./panel/onboarding/onboarding.component').then((c) => c.OnboardingComponent), + }, { path: 'app', loadChildren: () => import('./panel/panel.routes').then((r) => r.panelRoutes), @@ -24,15 +26,13 @@ export const appRoutes: Route[] = [ import('./panel/features/create-feature/feature-preview/widget-preview/widget-preview.component').then( (c) => c.WidgetPreviewComponent ), - data: { authGuardPipe: redirectUnauthorizedToLogin }, - canActivate: [AngularFireAuthGuard], + canActivate: [CanActivateRouteGuard], }, { path: 'project', loadComponent: () => import('./panel/create-project/create-project.component').then((c) => c.CreateProjectComponent), - data: { authGuardPipe: redirectUnauthorizedToLogin }, - canActivate: [AngularFireAuthGuard], + canActivate: [CanActivateRouteGuard], }, { path: 'client', diff --git a/apps/36-blocks/src/app/panel/guard/project.guard.ts b/apps/36-blocks/src/app/panel/guard/project.guard.ts deleted file mode 100644 index c37548ab..00000000 --- a/apps/36-blocks/src/app/panel/guard/project.guard.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable } from '@angular/core'; -import { UrlTree, Router } from '@angular/router'; -import { Observable, filter } from 'rxjs'; -import { take } from 'rxjs/operators'; -import { rootActions } from '../../core/ngrx/actions'; -import { select, Store } from '@ngrx/store'; -import { IAppState, selectAllProjectList } from '../../core/ngrx'; -import { IPaginatedResponse } from '@proxy/models/root-models'; -import { IProjects } from '@proxy/models/logs-models'; - -@Injectable({ - providedIn: 'root', -}) -export class ProjectGuard { - public getProject$: Observable>; - - constructor( - private router: Router, - private store: Store - ) { - this.getProject$ = this.store.pipe(select(selectAllProjectList)); - } - - canActivate(): Observable | Promise | boolean | UrlTree { - return new Promise((promiseResolve) => { - this.getProject$.pipe(take(1)).subscribe((res) => !res && this.store.dispatch(rootActions.getAllProject())); - this.getProject$ - .pipe( - filter((value) => value != null), - take(1) - ) - .subscribe((res) => { - if (res.data.length === 0) { - this.router.navigate(['/project']); - } else { - promiseResolve(true); - } - }); - }); - } -} diff --git a/apps/36-blocks/src/app/panel/layout/layout.component.html b/apps/36-blocks/src/app/panel/layout/layout.component.html index 6cb16af9..ce152ce8 100644 --- a/apps/36-blocks/src/app/panel/layout/layout.component.html +++ b/apps/36-blocks/src/app/panel/layout/layout.component.html @@ -3,6 +3,7 @@ class="flex flex-col transition-all duration-200 mat-drawer-content max-desktop:fixed max-desktop:z-[999] max-desktop:top-0 max-desktop:bottom-0 bg-color p-2" [class.mat-drawer-toggle-btn-hover]="sideNavService.isSideNavOpen()" [class]="!sideNavService.isSideNavOpen() ? 'overflow-hidden !w-[56px] p-1.5' : 'w-[260px]'" + [class.!hidden]="sideNavService.hideSidebar()" > @let clientSettings = clientSettings$ | async; @let clientList = clients$ | async; @let isMultipleClients = (clientList?.data?.length ?? 0) > 1; diff --git a/apps/36-blocks/src/app/panel/layout/layout.component.ts b/apps/36-blocks/src/app/panel/layout/layout.component.ts index 7435cb93..887966e1 100644 --- a/apps/36-blocks/src/app/panel/layout/layout.component.ts +++ b/apps/36-blocks/src/app/panel/layout/layout.component.ts @@ -38,6 +38,8 @@ import { environment } from '../../../environments/environment'; import { AuthService } from '@proxy/services/proxy/auth'; import { SideNavService } from './side-nav.service'; import { UiSettingsService } from './ui-settings.service'; +import { FeaturesService } from '@proxy/services/proxy/features'; +import { take } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'proxy-layout', @@ -85,6 +87,7 @@ export class LayoutComponent extends BaseComponent implements OnInit, OnDestroy private cdr = inject(ChangeDetectorRef); public sideNavService = inject(SideNavService); private uiSettings = inject(UiSettingsService); + private featuresService = inject(FeaturesService); constructor() { super(); @@ -118,6 +121,18 @@ export class LayoutComponent extends BaseComponent implements OnInit, OnDestroy if (event?.url?.startsWith('/widget-preview')) { (window as any).closeChatbot?.(); } + if (event?.url?.includes('/features/create')) { + this.featuresService + .getFeature({ itemsPerPage: 1, pageNo: 1 }) + .pipe(take(1)) + .subscribe((res) => { + const hasFeatures = (res?.data?.totalEntityCount ?? 0) > 0; + this.sideNavService.hideSidebar.set(!hasFeatures); + this.cdr.markForCheck(); + }); + } else { + this.sideNavService.hideSidebar.set(false); + } this.cdr.markForCheck(); }); } @@ -136,6 +151,28 @@ export class LayoutComponent extends BaseComponent implements OnInit, OnDestroy } }); + this.clientSettings$.pipe(takeUntil(this.destroy$)).subscribe((clientSettings) => { + if (clientSettings?.client) { + this.logInData$.pipe(take(1)).subscribe((existingLoginData) => { + if (!existingLoginData) { + this.store.dispatch( + logInActions.authenticatedAction({ + response: { + uid: String(clientSettings.client.id), + displayName: clientSettings.client.name, + email: clientSettings.client.email, + phoneNumber: clientSettings.client.mobile ?? null, + photoURL: null, + emailVerified: false, + jwtToken: this.authService.getTokenSync(), + }, + }) + ); + } + }); + } + }); + combineLatest([this.logInData$, this.clientSettings$]).subscribe(([loginData, clientSettings]) => { if (loginData && clientSettings) { this.rootService.generateToken({ source: 'chatbot' }).subscribe((res) => { diff --git a/apps/36-blocks/src/app/panel/layout/layout.routes.ts b/apps/36-blocks/src/app/panel/layout/layout.routes.ts index eef11cbe..7da8545f 100644 --- a/apps/36-blocks/src/app/panel/layout/layout.routes.ts +++ b/apps/36-blocks/src/app/panel/layout/layout.routes.ts @@ -1,9 +1,5 @@ import { Route } from '@angular/router'; import { CanActivateRouteGuard } from '../../website/home/authguard'; -import { redirectUnauthorizedTo } from '@angular/fire/compat/auth-guard'; -import { ProjectGuard } from '../guard/project.guard'; - -const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['login']); export const layoutRoutes: Route[] = [ { @@ -32,7 +28,6 @@ export const layoutRoutes: Route[] = [ loadComponent: () => import('../chatbot/chatbot.component').then((c) => c.ChatbotComponent), }, ], - data: { authGuardPipe: redirectUnauthorizedToLogin }, - canActivate: [CanActivateRouteGuard, ProjectGuard], + canActivate: [CanActivateRouteGuard], }, ]; diff --git a/apps/36-blocks/src/app/panel/layout/side-nav.service.ts b/apps/36-blocks/src/app/panel/layout/side-nav.service.ts index 191d511c..b39847ac 100644 --- a/apps/36-blocks/src/app/panel/layout/side-nav.service.ts +++ b/apps/36-blocks/src/app/panel/layout/side-nav.service.ts @@ -6,6 +6,7 @@ export class SideNavService { private uiSettings = inject(UiSettingsService); public isSideNavOpen = signal(this.uiSettings.sideNavOpen); + public hideSidebar = signal(false); public toggle(): void { const next = !this.isSideNavOpen(); diff --git a/apps/36-blocks/src/app/panel/onboarding/onboarding.component.html b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.html new file mode 100644 index 00000000..502e5bf8 --- /dev/null +++ b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.html @@ -0,0 +1,213 @@ +
+
+
+

Complete your profile

+

Just a few more details to get you started.

+
+
+ @if (onboardingError()) { + + } +
+ + + @if (getFieldError('name')) { + + } +
+
+ +
+ + + + + +
+ + + @if (dialCodeDropdownOpen()) { +
+ +
+ +
+ @if (filteredCountries.length === 0) { +

No countries found

+ } @else { + + + + } +
+ } + + @if (getFieldError('mobile')) { + + } +
+
+ + + @if (getFieldError('organizationName')) { + + } +
+ +
+
+
diff --git a/apps/36-blocks/src/app/panel/onboarding/onboarding.component.scss b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.scss new file mode 100644 index 00000000..7f26ddcb --- /dev/null +++ b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/36-blocks/src/app/panel/onboarding/onboarding.component.ts b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.ts new file mode 100644 index 00000000..23e48111 --- /dev/null +++ b/apps/36-blocks/src/app/panel/onboarding/onboarding.component.ts @@ -0,0 +1,182 @@ +import { + ChangeDetectionStrategy, + Component, + ElementRef, + HostListener, + ViewChild, + inject, + OnDestroy, + OnInit, + signal, +} from '@angular/core'; +import { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms'; +import { ScrollingModule } from '@angular/cdk/scrolling'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Subject } from 'rxjs'; +import { take, takeUntil } from 'rxjs/operators'; +import { AuthService } from '@proxy/services/proxy/auth'; +import { UsersService } from '@proxy/services/proxy/users'; +import { COUNTRIES_DATA, Country } from '../../../../../shared/assets/utils/countries-info'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'proxy-onboarding', + imports: [ReactiveFormsModule, ScrollingModule], + templateUrl: './onboarding.component.html', + styleUrl: './onboarding.component.scss', +}) +export class OnboardingComponent implements OnInit, OnDestroy { + private readonly activatedRoute = inject(ActivatedRoute); + private readonly router = inject(Router); + private readonly authService = inject(AuthService); + private readonly usersService = inject(UsersService); + private readonly destroy$ = new Subject(); + + public readonly onboardingSubmitting = signal(false); + public readonly onboardingError = signal(null); + public passwordVisible = false; + + private pendingJwtToken: string | null = null; + + public readonly allCountries: Country[] = COUNTRIES_DATA; + public selectedCountry: Country = COUNTRIES_DATA.find((country) => country.code === 'IN') ?? COUNTRIES_DATA[0]; + public readonly dialCodeDropdownOpen = signal(false); + public readonly dialCodeSearchQuery = signal(''); + + @ViewChild('dialCodeDropdownRef') private readonly dialCodeDropdownRef!: ElementRef; + + public get filteredCountries(): Country[] { + const query = this.dialCodeSearchQuery().trim().toLowerCase(); + if (!query) { + return this.allCountries; + } + return this.allCountries.filter( + (country) => + country.name.toLowerCase().includes(query) || + country.dialCode.includes(query) || + country.nativeName.toLowerCase().includes(query) + ); + } + + public toggleDialCodeDropdown(): void { + const isOpen = !this.dialCodeDropdownOpen(); + this.dialCodeDropdownOpen.set(isOpen); + if (isOpen) { + this.dialCodeSearchQuery.set(''); + } + } + + public selectCountry(country: Country): void { + this.selectedCountry = country; + this.dialCodeDropdownOpen.set(false); + this.dialCodeSearchQuery.set(''); + } + + public updateDialCodeSearch(value: string): void { + this.dialCodeSearchQuery.set(value); + } + + public trackCountryByCode(_index: number, country: Country): string { + return country.code; + } + + @HostListener('document:keydown.escape') + public closeDialCodeDropdownOnEscape(): void { + this.dialCodeDropdownOpen.set(false); + } + + @HostListener('document:click', ['$event']) + public closeDialCodeDropdownOnOutsideClick(event: MouseEvent): void { + if (this.dialCodeDropdownRef && !this.dialCodeDropdownRef.nativeElement.contains(event.target as Node)) { + this.dialCodeDropdownOpen.set(false); + } + } + + public readonly onboardingFormGroup = new FormGroup({ + name: new FormControl('', { + nonNullable: true, + validators: [Validators.required, Validators.minLength(2)], + }), + mobile: new FormControl('', { + nonNullable: true, + validators: [Validators.required, Validators.pattern(/^\d{10,15}$/)], + }), + organizationName: new FormControl('', { + nonNullable: true, + validators: [Validators.required, Validators.minLength(2)], + }), + }); + + public ngOnInit(): void { + this.pendingJwtToken = this.activatedRoute.snapshot.queryParamMap.get('token'); + } + + public ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + public getFieldError(fieldName: string): string | null { + const control = this.onboardingFormGroup.get(fieldName); + if (!control || !control.invalid || !control.touched) { + return null; + } + if (control.errors?.['required']) { + return 'This field is required.'; + } + if (control.errors?.['minlength']) { + const requiredLength = control.errors['minlength'].requiredLength; + return `Must be at least ${requiredLength} characters.`; + } + if (control.errors?.['pattern'] && fieldName === 'mobile') { + return 'Please enter a valid mobile number (10\u201315 digits).'; + } + return 'Invalid value.'; + } + + public submitOnboarding(): void { + if (this.onboardingFormGroup.invalid) { + this.onboardingFormGroup.markAllAsTouched(); + return; + } + this.onboardingError.set(null); + this.onboardingSubmitting.set(true); + const formValue = this.onboardingFormGroup.getRawValue(); + const dialCodeDigitsOnly = this.selectedCountry.dialCode.replace(/^\+/, ''); + const mobileWithDialCode = `${dialCodeDigitsOnly}${formValue.mobile}`; + + this.usersService + .submitOnboarding({ + user: { + name: formValue.name, + mobile: mobileWithDialCode, + }, + client: { + name: formValue.organizationName, + mobile: mobileWithDialCode, + }, + onboarding_token: this.pendingJwtToken ?? undefined, + }) + .pipe(take(1), takeUntil(this.destroy$)) + .subscribe({ + next: (response) => { + const jwtToken = response?.data?.token || response?.token; + if (jwtToken) { + this.authService.setTokenSync(jwtToken); + } + this.onboardingSubmitting.set(false); + this.router.navigate(['/app/features/create']); + }, + error: (error) => { + const errorBody = error?.error; + const resolvedMessage = + errorBody?.errors?.message || + errorBody?.data?.message || + errorBody?.message || + 'Onboarding failed. Please try again.'; + this.onboardingError.set(resolvedMessage); + this.onboardingSubmitting.set(false); + }, + }); + } +} diff --git a/apps/36-blocks/src/app/panel/panel.routes.ts b/apps/36-blocks/src/app/panel/panel.routes.ts index 7541981e..978772d3 100644 --- a/apps/36-blocks/src/app/panel/panel.routes.ts +++ b/apps/36-blocks/src/app/panel/panel.routes.ts @@ -1,9 +1,5 @@ import { Route } from '@angular/router'; -import { redirectUnauthorizedTo } from '@angular/fire/compat/auth-guard'; import { CanActivateRouteGuard } from '../website/home/authguard'; -import { ProjectGuard } from './guard/project.guard'; - -const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['login']); export const panelRoutes: Route[] = [ { @@ -32,7 +28,6 @@ export const panelRoutes: Route[] = [ loadComponent: () => import('./chatbot/chatbot.component').then((c) => c.ChatbotComponent), }, ], - data: { authGuardPipe: redirectUnauthorizedToLogin }, - canActivate: [CanActivateRouteGuard, ProjectGuard], + canActivate: [CanActivateRouteGuard], }, ]; diff --git a/apps/36-blocks/src/app/website/about/about.component.html b/apps/36-blocks/src/app/website/about/about.component.html index d832d251..dd3b1c90 100644 --- a/apps/36-blocks/src/app/website/about/about.component.html +++ b/apps/36-blocks/src/app/website/about/about.component.html @@ -1,26 +1,6 @@
-

Ready to get s

Ship auth in 5 minutes. Free forever on the Starter plan.

Get Started Free diff --git a/apps/36-blocks/src/app/website/contact/contact.component.html b/apps/36-blocks/src/app/website/contact/contact.component.html index c0b15829..b3311f26 100644 --- a/apps/36-blocks/src/app/website/contact/contact.component.html +++ b/apps/36-blocks/src/app/website/contact/contact.component.html @@ -1,26 +1,6 @@
-

(user ? true : this.router.createUrlTree(['']))) + ); } } diff --git a/apps/36-blocks/src/app/website/home/home.component.html b/apps/36-blocks/src/app/website/home/home.component.html index e2f5b2cf..cdd5f6f0 100644 --- a/apps/36-blocks/src/app/website/home/home.component.html +++ b/apps/36-blocks/src/app/website/home/home.component.html @@ -410,7 +410,7 @@

{{ card.title }} +

diff --git a/apps/36-blocks/src/app/website/login/google-one-tap.service.ts b/apps/36-blocks/src/app/website/login/google-one-tap.service.ts new file mode 100644 index 00000000..bf379162 --- /dev/null +++ b/apps/36-blocks/src/app/website/login/google-one-tap.service.ts @@ -0,0 +1,129 @@ +import { Injectable, NgZone, inject } from '@angular/core'; +import { Observable } from 'rxjs'; +import { DOCUMENT } from '@angular/common'; +import { environment } from '../../../environments/environment'; + +declare const google: { + accounts: { + id: { + initialize: (config: Record) => void; + prompt: ( + notification?: (notification: { isNotDisplayed: () => boolean; isSkippedMoment: () => boolean }) => void + ) => void; + renderButton: (parent: HTMLElement, options: Record) => void; + cancel: () => void; + }; + }; +}; + +export interface GoogleOneTapCredential { + credential: string; + select_by: string; +} + +@Injectable({ providedIn: 'root' }) +export class GoogleOneTapService { + private readonly ngZone = inject(NgZone); + private readonly document = inject(DOCUMENT); + + // GIS script is lazy-loaded only when the login page is visited — not in index.html + // This avoids loading a third-party script on every page of the app. + private gisScriptLoaded = false; + + // TODO (pending): Google One Tap is disabled until googleClientId is set in env-variables.ts + // Once the client ID is configured, this service will render the personalized + // "Continue as user@gmail.com" button and trigger the One Tap floating prompt. + // Fallback: the standard Firebase popup Google login remains active when isAvailable() returns false. + public isAvailable(): boolean { + return typeof google !== 'undefined' && !!google?.accounts?.id && !!environment.googleClientId; + } + + public loadScript(): Promise { + if (this.gisScriptLoaded || typeof google !== 'undefined') { + this.gisScriptLoaded = true; + return Promise.resolve(); + } + return new Promise((resolve) => { + let resolved = false; + const resolveOnce = (): void => { + if (!resolved) { + resolved = true; + resolve(); + } + }; + const timeoutId = setTimeout(resolveOnce, 3000); + const scriptElement = this.document.createElement('script'); + scriptElement.src = 'https://accounts.google.com/gsi/client'; + scriptElement.async = true; + scriptElement.defer = true; + scriptElement.onload = () => { + this.gisScriptLoaded = true; + clearTimeout(timeoutId); + resolveOnce(); + }; + scriptElement.onerror = () => { + clearTimeout(timeoutId); + resolveOnce(); + }; + this.document.head.appendChild(scriptElement); + }); + } + + public initialize(onCredentialReceived: (credential: GoogleOneTapCredential) => void): void { + // TODO (pending): Skipped until googleClientId is set in env-variables.ts + if (!this.isAvailable()) { + return; + } + google.accounts.id.initialize({ + client_id: environment.googleClientId, + callback: (credentialResponse: GoogleOneTapCredential) => { + this.ngZone.run(() => onCredentialReceived(credentialResponse)); + }, + auto_select: true, + cancel_on_tap_outside: false, + }); + } + + public prompt(): void { + // TODO (pending): Skipped until googleClientId is set in env-variables.ts + if (!this.isAvailable()) { + return; + } + google.accounts.id.prompt(); + } + + public renderButton(parentElement: HTMLElement, options: Record = {}): void { + // TODO (pending): Skipped until googleClientId is set in env-variables.ts + if (!this.isAvailable()) { + return; + } + google.accounts.id.renderButton(parentElement, { + type: 'standard', + theme: 'outline', + size: 'large', + text: 'continue_with', + shape: 'rectangular', + logo_alignment: 'left', + width: parentElement.offsetWidth || 400, + ...options, + }); + } + + public cancel(): void { + if (!this.isAvailable()) { + return; + } + google.accounts.id.cancel(); + } + + // TODO (pending): Call this instead of initialize()+prompt() separately once googleClientId is set + public initializeAsObservable(): Observable { + return new Observable((observer) => { + this.initialize((credentialResponse) => { + observer.next(credentialResponse); + }); + this.prompt(); + return () => this.cancel(); + }); + } +} diff --git a/apps/36-blocks/src/app/website/login/login-page.component.html b/apps/36-blocks/src/app/website/login/login-page.component.html new file mode 100644 index 00000000..d5324b72 --- /dev/null +++ b/apps/36-blocks/src/app/website/login/login-page.component.html @@ -0,0 +1,249 @@ +
+
+ +
+

Welcome back

+

Log in to your 36Blocks account.

+
+ + +
+ + @if (loginErrors().length > 0) { + + } + + +
+ +
+ + + @if (getFieldError('email')) { + + } +
+ + +
+ +
+ + +
+ @if (getFieldError('password')) { + + } +
+ + + +
+ + +
+ +
+ or continue with +
+
+ + + @if (isGisAvailable) { + +
+
+ @if (googleLoginInProgress()) { +
+ + Signing in… +
+ } +
+ } @else { + + + } + + +

+ Don't have an account? + + Sign up free + +

+
+
+
diff --git a/apps/36-blocks/src/app/website/login/login-page.component.scss b/apps/36-blocks/src/app/website/login/login-page.component.scss new file mode 100644 index 00000000..7f26ddcb --- /dev/null +++ b/apps/36-blocks/src/app/website/login/login-page.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/36-blocks/src/app/website/login/login-page.component.ts b/apps/36-blocks/src/app/website/login/login-page.component.ts new file mode 100644 index 00000000..b31472b5 --- /dev/null +++ b/apps/36-blocks/src/app/website/login/login-page.component.ts @@ -0,0 +1,139 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + ViewChild, + inject, + OnDestroy, + OnInit, +} from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { Actions, ofType } from '@ngrx/effects'; +import { signal } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import * as logInActions from '../home/ngrx/actions/login.action'; +import { GoogleOneTapService } from './google-one-tap.service'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'proxy-login-page', + imports: [ReactiveFormsModule, RouterModule], + templateUrl: './login-page.component.html', + styleUrl: './login-page.component.scss', +}) +export class LoginPageComponent implements OnInit, AfterViewInit, OnDestroy { + private readonly store = inject(Store); + private readonly actions$ = inject(Actions); + private readonly router = inject(Router); + private readonly googleOneTapService = inject(GoogleOneTapService); + private readonly destroy$ = new Subject(); + + @ViewChild('googleButtonContainer') private readonly googleButtonContainer!: ElementRef; + + public readonly loginInProgress = signal(false); + public readonly googleLoginInProgress = signal(false); + public readonly loginErrors = signal([]); + public passwordVisible = false; + + public readonly loginFormGroup = new FormGroup({ + email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }), + password: new FormControl('', { nonNullable: true, validators: [Validators.required] }), + }); + + public ngOnInit(): void { + // GIS script is lazy-loaded here — only fetched when the user visits /login, not on every page + // TODO (pending): GIS One Tap initialization — active only when googleClientId is set in env-variables.ts + // When active: intercepts Google credential here instead of going through Firebase popup + this.googleOneTapService.loadScript().then(() => { + this.googleOneTapService.initialize((credentialResponse) => { + this.googleLoginInProgress.set(true); + this.loginErrors.set([]); + this.store.dispatch(logInActions.googleOneTapCredential({ idToken: credentialResponse.credential })); + }); + }); + + this.actions$ + .pipe(ofType(logInActions.emailLoginOnboardingPending), takeUntil(this.destroy$)) + .subscribe(({ pendingJwtToken }) => { + this.loginInProgress.set(false); + this.router.navigate(['/onboarding'], { queryParams: { token: pendingJwtToken } }); + }); + + this.actions$.pipe(ofType(logInActions.emailLoginSuccess), takeUntil(this.destroy$)).subscribe(() => { + this.loginInProgress.set(false); + this.store.dispatch(logInActions.getUserAction()); + }); + + this.actions$.pipe(ofType(logInActions.logInActionComplete), takeUntil(this.destroy$)).subscribe(() => { + this.googleLoginInProgress.set(false); + }); + + this.actions$.pipe(ofType(logInActions.logInActionError), takeUntil(this.destroy$)).subscribe(({ errors }) => { + this.loginInProgress.set(false); + this.googleLoginInProgress.set(false); + this.loginErrors.set(errors); + }); + } + + public ngAfterViewInit(): void { + // TODO (pending): GIS rendered button — shows personalized "Continue as user@gmail.com" + // Only renders when googleClientId is set in env-variables.ts; falls back to manual button below + if (this.googleButtonContainer?.nativeElement) { + this.googleOneTapService.renderButton(this.googleButtonContainer.nativeElement); + } + this.googleOneTapService.prompt(); + } + + public ngOnDestroy(): void { + this.googleOneTapService.cancel(); + this.destroy$.next(); + this.destroy$.complete(); + } + + public togglePasswordVisibility(): void { + this.passwordVisible = !this.passwordVisible; + } + + public getFieldError(fieldName: string): string | null { + const control = this.loginFormGroup.get(fieldName); + if (!control || !control.invalid || !control.touched) { + return null; + } + if (control.errors?.['required']) { + return 'This field is required.'; + } + if (control.errors?.['email']) { + return 'Please enter a valid email address.'; + } + return 'Invalid value.'; + } + + public submitLogin(): void { + if (this.loginFormGroup.invalid) { + this.loginFormGroup.markAllAsTouched(); + return; + } + this.loginErrors.set([]); + this.loginInProgress.set(true); + const formValue = this.loginFormGroup.getRawValue(); + this.store.dispatch(logInActions.emailLoginAction({ email: formValue.email, password: formValue.password })); + } + + public loginWithGoogle(): void { + this.loginErrors.set([]); + this.googleLoginInProgress.set(true); + this.store.dispatch(logInActions.logInAction()); + } + + // TODO (pending): Switch Google button to GIS rendered version once googleClientId is configured + // When true: shows native Google button with personalized email ("Continue as user@gmail.com") + // When false: falls back to standard Firebase popup login button + public get isGisAvailable(): boolean { + return this.googleOneTapService.isAvailable(); + } +} diff --git a/apps/36-blocks/src/app/website/pricing/pricing.component.html b/apps/36-blocks/src/app/website/pricing/pricing.component.html index 375ee7c9..388bab65 100644 --- a/apps/36-blocks/src/app/website/pricing/pricing.component.html +++ b/apps/36-blocks/src/app/website/pricing/pricing.component.html @@ -1,13 +1,6 @@
-
- +

Pricing plans

. +

+
+ } @else { + +
+ + @if (registrationErrors().length > 0) { + + } + + +
+ + + @if (getFieldError('email')) { + + } +
+ + +
+ +
+ + +
+ @if (getFieldError('password')) { + + } + + @if ( + registrationFormGroup.get('password')?.dirty || registrationFormGroup.get('password')?.touched + ) { +
    + @for (rule of passwordRules; track rule.key) { +
  • + @if (rule.met) { + + {{ rule.label }} + } @else { + + {{ rule.label }} + } +
  • + } +
+ } +
+ + + + + +

+ Already have an account? + + Log in + +

+
+ } +
+

diff --git a/apps/36-blocks/src/app/website/register/register-page.component.scss b/apps/36-blocks/src/app/website/register/register-page.component.scss new file mode 100644 index 00000000..7f26ddcb --- /dev/null +++ b/apps/36-blocks/src/app/website/register/register-page.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/36-blocks/src/app/website/register/register-page.component.ts b/apps/36-blocks/src/app/website/register/register-page.component.ts new file mode 100644 index 00000000..588076d8 --- /dev/null +++ b/apps/36-blocks/src/app/website/register/register-page.component.ts @@ -0,0 +1,107 @@ +import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { CustomValidators } from '@proxy/custom-validator'; +import { Store } from '@ngrx/store'; +import { toSignal } from '@angular/core/rxjs-interop'; +import * as registrationActions from '../home/ngrx/actions/registration.action'; +import { + selectRegistrationInProgress, + selectRegistrationSuccess, + selectRegistrationErrors, + selectRegisteredEmail, +} from '../home/ngrx/selector/registration.selector'; + +export interface PasswordRule { + key: string; + label: string; + met: boolean; +} + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'proxy-register-page', + imports: [ReactiveFormsModule, RouterModule], + templateUrl: './register-page.component.html', + styleUrl: './register-page.component.scss', +}) +export class RegisterPageComponent implements OnInit, OnDestroy { + private readonly store = inject(Store); + + public readonly registrationInProgress = toSignal(this.store.select(selectRegistrationInProgress), { + initialValue: false, + }); + public readonly registrationSuccess = toSignal(this.store.select(selectRegistrationSuccess), { + initialValue: false, + }); + public readonly registrationErrors = toSignal(this.store.select(selectRegistrationErrors), { + initialValue: [] as string[], + }); + public readonly registeredEmail = toSignal(this.store.select(selectRegisteredEmail), { + initialValue: null as string | null, + }); + + public readonly registrationFormGroup = new FormGroup({ + email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }), + password: new FormControl('', { + nonNullable: true, + validators: [Validators.required, CustomValidators.passwordStrength()], + }), + }); + + public passwordVisible = false; + + public ngOnInit(): void { + this.store.dispatch(registrationActions.registrationResetAction()); + } + + public ngOnDestroy(): void { + this.store.dispatch(registrationActions.registrationResetAction()); + } + + public togglePasswordVisibility(): void { + this.passwordVisible = !this.passwordVisible; + } + + public get passwordRules(): PasswordRule[] { + const control = this.registrationFormGroup.get('password'); + const value: string = control?.value ?? ''; + return [ + { key: 'minLength', label: 'At least 8 characters', met: value.length >= 8 }, + { key: 'uppercase', label: 'At least one uppercase letter (A–Z)', met: /[A-Z]/.test(value) }, + { key: 'lowercase', label: 'At least one lowercase letter (a–z)', met: /[a-z]/.test(value) }, + { key: 'number', label: 'At least one number (0–9)', met: /[0-9]/.test(value) }, + { key: 'symbol', label: 'At least one symbol (!@#$…)', met: /[^A-Za-z0-9]/.test(value) }, + ]; + } + + public getFieldError(fieldName: string): string | null { + const control = this.registrationFormGroup.get(fieldName); + if (!control || !control.invalid || !control.touched) { + return null; + } + if (control.errors?.['required']) { + return 'This field is required.'; + } + if (control.errors?.['email']) { + return 'Please enter a valid email address.'; + } + return null; + } + + public submitRegistration(): void { + if (this.registrationFormGroup.invalid) { + this.registrationFormGroup.markAllAsTouched(); + return; + } + const formValue = this.registrationFormGroup.getRawValue(); + this.store.dispatch( + registrationActions.registrationSubmitAction({ + payload: { + email: formValue.email, + password: formValue.password, + }, + }) + ); + } +} diff --git a/apps/36-blocks/src/app/website/security/security.component.html b/apps/36-blocks/src/app/website/security/security.component.html index b1a0d1f9..c0616ff5 100644 --- a/apps/36-blocks/src/app/website/security/security.component.html +++ b/apps/36-blocks/src/app/website/security/security.component.html @@ -1,26 +1,6 @@
-

-

Terms of Service

diff --git a/apps/36-blocks/src/app/website/website.routes.ts b/apps/36-blocks/src/app/website/website.routes.ts index 983247d7..77e5f6af 100644 --- a/apps/36-blocks/src/app/website/website.routes.ts +++ b/apps/36-blocks/src/app/website/website.routes.ts @@ -36,6 +36,14 @@ export const websiteRoutes: Route[] = [ path: 'contact', loadComponent: () => import('./contact/contact.component').then((c) => c.ContactComponent), }, + { + path: 'register', + loadComponent: () => import('./register/register-page.component').then((c) => c.RegisterPageComponent), + }, + { + path: 'login', + loadComponent: () => import('./login/login-page.component').then((c) => c.LoginPageComponent), + }, ], }, ]; diff --git a/apps/36-blocks/src/assets/images/flags/ad.png b/apps/36-blocks/src/assets/images/flags/ad.png new file mode 100644 index 00000000..fd1e7453 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ad.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ae.png b/apps/36-blocks/src/assets/images/flags/ae.png new file mode 100644 index 00000000..becb5382 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ae.png differ diff --git a/apps/36-blocks/src/assets/images/flags/af.png b/apps/36-blocks/src/assets/images/flags/af.png new file mode 100644 index 00000000..8bfad1e5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/af.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ag.png b/apps/36-blocks/src/assets/images/flags/ag.png new file mode 100644 index 00000000..33eac127 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ag.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ai.png b/apps/36-blocks/src/assets/images/flags/ai.png new file mode 100644 index 00000000..757d2b0f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ai.png differ diff --git a/apps/36-blocks/src/assets/images/flags/al.png b/apps/36-blocks/src/assets/images/flags/al.png new file mode 100644 index 00000000..468caf52 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/al.png differ diff --git a/apps/36-blocks/src/assets/images/flags/am.png b/apps/36-blocks/src/assets/images/flags/am.png new file mode 100644 index 00000000..c9444866 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/am.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ao.png b/apps/36-blocks/src/assets/images/flags/ao.png new file mode 100644 index 00000000..0239e0f6 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ao.png differ diff --git a/apps/36-blocks/src/assets/images/flags/aq.png b/apps/36-blocks/src/assets/images/flags/aq.png new file mode 100644 index 00000000..5041c1f8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/aq.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ar.png b/apps/36-blocks/src/assets/images/flags/ar.png new file mode 100644 index 00000000..75f031cb Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ar.png differ diff --git a/apps/36-blocks/src/assets/images/flags/as.png b/apps/36-blocks/src/assets/images/flags/as.png new file mode 100644 index 00000000..78cb337a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/as.png differ diff --git a/apps/36-blocks/src/assets/images/flags/at.png b/apps/36-blocks/src/assets/images/flags/at.png new file mode 100644 index 00000000..57bfd8a4 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/at.png differ diff --git a/apps/36-blocks/src/assets/images/flags/au.png b/apps/36-blocks/src/assets/images/flags/au.png new file mode 100644 index 00000000..95767e74 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/au.png differ diff --git a/apps/36-blocks/src/assets/images/flags/aw.png b/apps/36-blocks/src/assets/images/flags/aw.png new file mode 100644 index 00000000..fa1d0103 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/aw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ax.png b/apps/36-blocks/src/assets/images/flags/ax.png new file mode 100644 index 00000000..0a6b0b1f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ax.png differ diff --git a/apps/36-blocks/src/assets/images/flags/az.png b/apps/36-blocks/src/assets/images/flags/az.png new file mode 100644 index 00000000..d4325183 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/az.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ba.png b/apps/36-blocks/src/assets/images/flags/ba.png new file mode 100644 index 00000000..4c336031 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ba.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bb.png b/apps/36-blocks/src/assets/images/flags/bb.png new file mode 100644 index 00000000..71fe685c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bb.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bd.png b/apps/36-blocks/src/assets/images/flags/bd.png new file mode 100644 index 00000000..a85f5cf5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bd.png differ diff --git a/apps/36-blocks/src/assets/images/flags/be.png b/apps/36-blocks/src/assets/images/flags/be.png new file mode 100644 index 00000000..f6c41980 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/be.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bf.png b/apps/36-blocks/src/assets/images/flags/bf.png new file mode 100644 index 00000000..7034f790 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bg.png b/apps/36-blocks/src/assets/images/flags/bg.png new file mode 100644 index 00000000..25808e0f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bh.png b/apps/36-blocks/src/assets/images/flags/bh.png new file mode 100644 index 00000000..aaa12380 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bi.png b/apps/36-blocks/src/assets/images/flags/bi.png new file mode 100644 index 00000000..718d810d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bi.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bj.png b/apps/36-blocks/src/assets/images/flags/bj.png new file mode 100644 index 00000000..0400a357 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bj.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bm.png b/apps/36-blocks/src/assets/images/flags/bm.png new file mode 100644 index 00000000..09a0760e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bn.png b/apps/36-blocks/src/assets/images/flags/bn.png new file mode 100644 index 00000000..32456aba Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bo.png b/apps/36-blocks/src/assets/images/flags/bo.png new file mode 100644 index 00000000..f8a0d2c0 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bo.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bq.png b/apps/36-blocks/src/assets/images/flags/bq.png new file mode 100644 index 00000000..fc7ef2d2 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bq.png differ diff --git a/apps/36-blocks/src/assets/images/flags/br.png b/apps/36-blocks/src/assets/images/flags/br.png new file mode 100644 index 00000000..fdea752d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/br.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bs.png b/apps/36-blocks/src/assets/images/flags/bs.png new file mode 100644 index 00000000..8b3edc3a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bs.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bt.png b/apps/36-blocks/src/assets/images/flags/bt.png new file mode 100644 index 00000000..3c26d439 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bv.png b/apps/36-blocks/src/assets/images/flags/bv.png new file mode 100644 index 00000000..56062603 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bw.png b/apps/36-blocks/src/assets/images/flags/bw.png new file mode 100644 index 00000000..d6519bf0 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/by.png b/apps/36-blocks/src/assets/images/flags/by.png new file mode 100644 index 00000000..b95a200c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/by.png differ diff --git a/apps/36-blocks/src/assets/images/flags/bz.png b/apps/36-blocks/src/assets/images/flags/bz.png new file mode 100644 index 00000000..6140a7c5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/bz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ca.png b/apps/36-blocks/src/assets/images/flags/ca.png new file mode 100644 index 00000000..27a9b2f7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ca.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cc.png b/apps/36-blocks/src/assets/images/flags/cc.png new file mode 100644 index 00000000..bea814c1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cd.png b/apps/36-blocks/src/assets/images/flags/cd.png new file mode 100644 index 00000000..85174d81 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cd.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cf.png b/apps/36-blocks/src/assets/images/flags/cf.png new file mode 100644 index 00000000..090c969d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cg.png b/apps/36-blocks/src/assets/images/flags/cg.png new file mode 100644 index 00000000..8a08a578 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ch.png b/apps/36-blocks/src/assets/images/flags/ch.png new file mode 100644 index 00000000..97f6cf22 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ch.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ci.png b/apps/36-blocks/src/assets/images/flags/ci.png new file mode 100644 index 00000000..309aa494 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ci.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ck.png b/apps/36-blocks/src/assets/images/flags/ck.png new file mode 100644 index 00000000..a4b772a1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ck.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cl.png b/apps/36-blocks/src/assets/images/flags/cl.png new file mode 100644 index 00000000..63221a8f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cm.png b/apps/36-blocks/src/assets/images/flags/cm.png new file mode 100644 index 00000000..9920b3ad Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cn.png b/apps/36-blocks/src/assets/images/flags/cn.png new file mode 100644 index 00000000..5524030f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/co.png b/apps/36-blocks/src/assets/images/flags/co.png new file mode 100644 index 00000000..4e954f9f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/co.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cr.png b/apps/36-blocks/src/assets/images/flags/cr.png new file mode 100644 index 00000000..7565c71d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cu.png b/apps/36-blocks/src/assets/images/flags/cu.png new file mode 100644 index 00000000..2a2ab70d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cv.png b/apps/36-blocks/src/assets/images/flags/cv.png new file mode 100644 index 00000000..38f9393b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cw.png b/apps/36-blocks/src/assets/images/flags/cw.png new file mode 100644 index 00000000..2b152737 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cx.png b/apps/36-blocks/src/assets/images/flags/cx.png new file mode 100644 index 00000000..4cf2b541 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cx.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cy.png b/apps/36-blocks/src/assets/images/flags/cy.png new file mode 100644 index 00000000..81198b21 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cy.png differ diff --git a/apps/36-blocks/src/assets/images/flags/cz.png b/apps/36-blocks/src/assets/images/flags/cz.png new file mode 100644 index 00000000..2230ed3e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/cz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/de.png b/apps/36-blocks/src/assets/images/flags/de.png new file mode 100644 index 00000000..a60a67d3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/de.png differ diff --git a/apps/36-blocks/src/assets/images/flags/dj.png b/apps/36-blocks/src/assets/images/flags/dj.png new file mode 100644 index 00000000..27c03c65 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/dj.png differ diff --git a/apps/36-blocks/src/assets/images/flags/dk.png b/apps/36-blocks/src/assets/images/flags/dk.png new file mode 100644 index 00000000..1c8f97e5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/dk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/dm.png b/apps/36-blocks/src/assets/images/flags/dm.png new file mode 100644 index 00000000..a19a632e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/dm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/do.png b/apps/36-blocks/src/assets/images/flags/do.png new file mode 100644 index 00000000..b9a743f5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/do.png differ diff --git a/apps/36-blocks/src/assets/images/flags/dz.png b/apps/36-blocks/src/assets/images/flags/dz.png new file mode 100644 index 00000000..17290331 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/dz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ec.png b/apps/36-blocks/src/assets/images/flags/ec.png new file mode 100644 index 00000000..c7e081a6 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ec.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ee.png b/apps/36-blocks/src/assets/images/flags/ee.png new file mode 100644 index 00000000..d9aa9661 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ee.png differ diff --git a/apps/36-blocks/src/assets/images/flags/eg.png b/apps/36-blocks/src/assets/images/flags/eg.png new file mode 100644 index 00000000..9f3fbb50 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/eg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/eh.png b/apps/36-blocks/src/assets/images/flags/eh.png new file mode 100644 index 00000000..46d51eb3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/eh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/er.png b/apps/36-blocks/src/assets/images/flags/er.png new file mode 100644 index 00000000..4e45d514 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/er.png differ diff --git a/apps/36-blocks/src/assets/images/flags/es.png b/apps/36-blocks/src/assets/images/flags/es.png new file mode 100644 index 00000000..e06d7a01 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/es.png differ diff --git a/apps/36-blocks/src/assets/images/flags/et.png b/apps/36-blocks/src/assets/images/flags/et.png new file mode 100644 index 00000000..5ec27ed2 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/et.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fi.png b/apps/36-blocks/src/assets/images/flags/fi.png new file mode 100644 index 00000000..642e2248 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fi.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fj.png b/apps/36-blocks/src/assets/images/flags/fj.png new file mode 100644 index 00000000..adeb4f1a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fj.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fk.png b/apps/36-blocks/src/assets/images/flags/fk.png new file mode 100644 index 00000000..cef5ec36 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fm.png b/apps/36-blocks/src/assets/images/flags/fm.png new file mode 100644 index 00000000..816d313b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fo.png b/apps/36-blocks/src/assets/images/flags/fo.png new file mode 100644 index 00000000..e0f45e81 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fo.png differ diff --git a/apps/36-blocks/src/assets/images/flags/fr.png b/apps/36-blocks/src/assets/images/flags/fr.png new file mode 100644 index 00000000..b6065598 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/fr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ga.png b/apps/36-blocks/src/assets/images/flags/ga.png new file mode 100644 index 00000000..3e2f30ed Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ga.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gb.png b/apps/36-blocks/src/assets/images/flags/gb.png new file mode 100644 index 00000000..d476f54d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gb.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gd.png b/apps/36-blocks/src/assets/images/flags/gd.png new file mode 100644 index 00000000..8f17b070 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gd.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ge.png b/apps/36-blocks/src/assets/images/flags/ge.png new file mode 100644 index 00000000..f0028d86 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ge.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gf.png b/apps/36-blocks/src/assets/images/flags/gf.png new file mode 100644 index 00000000..9c109485 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gg.png b/apps/36-blocks/src/assets/images/flags/gg.png new file mode 100644 index 00000000..cff151e3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gh.png b/apps/36-blocks/src/assets/images/flags/gh.png new file mode 100644 index 00000000..6cc9d8f4 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gi.png b/apps/36-blocks/src/assets/images/flags/gi.png new file mode 100644 index 00000000..9a6d2b43 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gi.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gl.png b/apps/36-blocks/src/assets/images/flags/gl.png new file mode 100644 index 00000000..68fa989f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gm.png b/apps/36-blocks/src/assets/images/flags/gm.png new file mode 100644 index 00000000..55227298 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gn.png b/apps/36-blocks/src/assets/images/flags/gn.png new file mode 100644 index 00000000..3788ae99 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gp.png b/apps/36-blocks/src/assets/images/flags/gp.png new file mode 100644 index 00000000..4044e8fd Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gp.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gq.png b/apps/36-blocks/src/assets/images/flags/gq.png new file mode 100644 index 00000000..ccb0022f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gq.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gr.png b/apps/36-blocks/src/assets/images/flags/gr.png new file mode 100644 index 00000000..3fec1ae7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gs.png b/apps/36-blocks/src/assets/images/flags/gs.png new file mode 100644 index 00000000..805e76fc Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gs.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gt.png b/apps/36-blocks/src/assets/images/flags/gt.png new file mode 100644 index 00000000..c3289e91 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gu.png b/apps/36-blocks/src/assets/images/flags/gu.png new file mode 100644 index 00000000..2af6662f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gw.png b/apps/36-blocks/src/assets/images/flags/gw.png new file mode 100644 index 00000000..64b831dd Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/gy.png b/apps/36-blocks/src/assets/images/flags/gy.png new file mode 100644 index 00000000..4b56e5e2 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/gy.png differ diff --git a/apps/36-blocks/src/assets/images/flags/hk.png b/apps/36-blocks/src/assets/images/flags/hk.png new file mode 100644 index 00000000..9ad5f438 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/hk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/hm.png b/apps/36-blocks/src/assets/images/flags/hm.png new file mode 100644 index 00000000..fb5c0155 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/hm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/hn.png b/apps/36-blocks/src/assets/images/flags/hn.png new file mode 100644 index 00000000..cfae0ba5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/hn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/hr.png b/apps/36-blocks/src/assets/images/flags/hr.png new file mode 100644 index 00000000..32e2dc33 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/hr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ht.png b/apps/36-blocks/src/assets/images/flags/ht.png new file mode 100644 index 00000000..561b1c5f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ht.png differ diff --git a/apps/36-blocks/src/assets/images/flags/hu.png b/apps/36-blocks/src/assets/images/flags/hu.png new file mode 100644 index 00000000..5d67b386 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/hu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/id.png b/apps/36-blocks/src/assets/images/flags/id.png new file mode 100644 index 00000000..4d59754a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/id.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ie.png b/apps/36-blocks/src/assets/images/flags/ie.png new file mode 100644 index 00000000..4fe751fe Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ie.png differ diff --git a/apps/36-blocks/src/assets/images/flags/il.png b/apps/36-blocks/src/assets/images/flags/il.png new file mode 100644 index 00000000..a760e5fc Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/il.png differ diff --git a/apps/36-blocks/src/assets/images/flags/im.png b/apps/36-blocks/src/assets/images/flags/im.png new file mode 100644 index 00000000..b3074aef Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/im.png differ diff --git a/apps/36-blocks/src/assets/images/flags/in.png b/apps/36-blocks/src/assets/images/flags/in.png new file mode 100644 index 00000000..39711f0e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/in.png differ diff --git a/apps/36-blocks/src/assets/images/flags/io.png b/apps/36-blocks/src/assets/images/flags/io.png new file mode 100644 index 00000000..75520a33 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/io.png differ diff --git a/apps/36-blocks/src/assets/images/flags/iq.png b/apps/36-blocks/src/assets/images/flags/iq.png new file mode 100644 index 00000000..b7b72273 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/iq.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ir.png b/apps/36-blocks/src/assets/images/flags/ir.png new file mode 100644 index 00000000..e189229c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ir.png differ diff --git a/apps/36-blocks/src/assets/images/flags/is.png b/apps/36-blocks/src/assets/images/flags/is.png new file mode 100644 index 00000000..b223debc Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/is.png differ diff --git a/apps/36-blocks/src/assets/images/flags/it.png b/apps/36-blocks/src/assets/images/flags/it.png new file mode 100644 index 00000000..1a15af42 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/it.png differ diff --git a/apps/36-blocks/src/assets/images/flags/je.png b/apps/36-blocks/src/assets/images/flags/je.png new file mode 100644 index 00000000..6d385475 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/je.png differ diff --git a/apps/36-blocks/src/assets/images/flags/jm.png b/apps/36-blocks/src/assets/images/flags/jm.png new file mode 100644 index 00000000..d29b036a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/jm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/jo.png b/apps/36-blocks/src/assets/images/flags/jo.png new file mode 100644 index 00000000..432e4f11 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/jo.png differ diff --git a/apps/36-blocks/src/assets/images/flags/jp.png b/apps/36-blocks/src/assets/images/flags/jp.png new file mode 100644 index 00000000..ef075bcd Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/jp.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ke.png b/apps/36-blocks/src/assets/images/flags/ke.png new file mode 100644 index 00000000..74126a3a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ke.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kg.png b/apps/36-blocks/src/assets/images/flags/kg.png new file mode 100644 index 00000000..77b79c14 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kh.png b/apps/36-blocks/src/assets/images/flags/kh.png new file mode 100644 index 00000000..e908725d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ki.png b/apps/36-blocks/src/assets/images/flags/ki.png new file mode 100644 index 00000000..49ca4c9a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ki.png differ diff --git a/apps/36-blocks/src/assets/images/flags/km.png b/apps/36-blocks/src/assets/images/flags/km.png new file mode 100644 index 00000000..b24ac0db Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/km.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kn.png b/apps/36-blocks/src/assets/images/flags/kn.png new file mode 100644 index 00000000..a441089b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kp.png b/apps/36-blocks/src/assets/images/flags/kp.png new file mode 100644 index 00000000..3888d57e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kp.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kr.png b/apps/36-blocks/src/assets/images/flags/kr.png new file mode 100644 index 00000000..5aaef195 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kw.png b/apps/36-blocks/src/assets/images/flags/kw.png new file mode 100644 index 00000000..62c6e414 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ky.png b/apps/36-blocks/src/assets/images/flags/ky.png new file mode 100644 index 00000000..99c4e142 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ky.png differ diff --git a/apps/36-blocks/src/assets/images/flags/kz.png b/apps/36-blocks/src/assets/images/flags/kz.png new file mode 100644 index 00000000..f38537b7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/kz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/la.png b/apps/36-blocks/src/assets/images/flags/la.png new file mode 100644 index 00000000..855509fb Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/la.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lb.png b/apps/36-blocks/src/assets/images/flags/lb.png new file mode 100644 index 00000000..3c9a624c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lb.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lc.png b/apps/36-blocks/src/assets/images/flags/lc.png new file mode 100644 index 00000000..4d81abc3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/li.png b/apps/36-blocks/src/assets/images/flags/li.png new file mode 100644 index 00000000..f80a6583 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/li.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lk.png b/apps/36-blocks/src/assets/images/flags/lk.png new file mode 100644 index 00000000..626395a7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lr.png b/apps/36-blocks/src/assets/images/flags/lr.png new file mode 100644 index 00000000..0ae8b5e6 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ls.png b/apps/36-blocks/src/assets/images/flags/ls.png new file mode 100644 index 00000000..c277d325 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ls.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lt.png b/apps/36-blocks/src/assets/images/flags/lt.png new file mode 100644 index 00000000..ed5231f3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lu.png b/apps/36-blocks/src/assets/images/flags/lu.png new file mode 100644 index 00000000..3fa288d1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/lv.png b/apps/36-blocks/src/assets/images/flags/lv.png new file mode 100644 index 00000000..ce27b5e3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/lv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ly.png b/apps/36-blocks/src/assets/images/flags/ly.png new file mode 100644 index 00000000..bee5cfef Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ly.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ma.png b/apps/36-blocks/src/assets/images/flags/ma.png new file mode 100644 index 00000000..863a5057 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ma.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mc.png b/apps/36-blocks/src/assets/images/flags/mc.png new file mode 100644 index 00000000..d0063b68 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/md.png b/apps/36-blocks/src/assets/images/flags/md.png new file mode 100644 index 00000000..0cb330a3 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/md.png differ diff --git a/apps/36-blocks/src/assets/images/flags/me.png b/apps/36-blocks/src/assets/images/flags/me.png new file mode 100644 index 00000000..7430427b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/me.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mf.png b/apps/36-blocks/src/assets/images/flags/mf.png new file mode 100644 index 00000000..b6065598 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mg.png b/apps/36-blocks/src/assets/images/flags/mg.png new file mode 100644 index 00000000..470be988 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mh.png b/apps/36-blocks/src/assets/images/flags/mh.png new file mode 100644 index 00000000..f1793539 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mk.png b/apps/36-blocks/src/assets/images/flags/mk.png new file mode 100644 index 00000000..46d1cb08 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ml.png b/apps/36-blocks/src/assets/images/flags/ml.png new file mode 100644 index 00000000..427d9d3b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ml.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mm.png b/apps/36-blocks/src/assets/images/flags/mm.png new file mode 100644 index 00000000..473e622a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mn.png b/apps/36-blocks/src/assets/images/flags/mn.png new file mode 100644 index 00000000..608ac2cc Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mo.png b/apps/36-blocks/src/assets/images/flags/mo.png new file mode 100644 index 00000000..c0516f99 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mo.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mp.png b/apps/36-blocks/src/assets/images/flags/mp.png new file mode 100644 index 00000000..72b44eb5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mp.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mq.png b/apps/36-blocks/src/assets/images/flags/mq.png new file mode 100644 index 00000000..cf9b0e7f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mq.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mr.png b/apps/36-blocks/src/assets/images/flags/mr.png new file mode 100644 index 00000000..aa016790 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ms.png b/apps/36-blocks/src/assets/images/flags/ms.png new file mode 100644 index 00000000..da5f849c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ms.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mt.png b/apps/36-blocks/src/assets/images/flags/mt.png new file mode 100644 index 00000000..53d8c468 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mu.png b/apps/36-blocks/src/assets/images/flags/mu.png new file mode 100644 index 00000000..8a5645fd Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mv.png b/apps/36-blocks/src/assets/images/flags/mv.png new file mode 100644 index 00000000..727768ac Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mw.png b/apps/36-blocks/src/assets/images/flags/mw.png new file mode 100644 index 00000000..6a52c2e8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mx.png b/apps/36-blocks/src/assets/images/flags/mx.png new file mode 100644 index 00000000..b0f21fa7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mx.png differ diff --git a/apps/36-blocks/src/assets/images/flags/my.png b/apps/36-blocks/src/assets/images/flags/my.png new file mode 100644 index 00000000..30275a73 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/my.png differ diff --git a/apps/36-blocks/src/assets/images/flags/mz.png b/apps/36-blocks/src/assets/images/flags/mz.png new file mode 100644 index 00000000..aacf3be8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/mz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/na.png b/apps/36-blocks/src/assets/images/flags/na.png new file mode 100644 index 00000000..12bc3aa1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/na.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nc.png b/apps/36-blocks/src/assets/images/flags/nc.png new file mode 100644 index 00000000..c7e1b42e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ne.png b/apps/36-blocks/src/assets/images/flags/ne.png new file mode 100644 index 00000000..b534b39f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ne.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nf.png b/apps/36-blocks/src/assets/images/flags/nf.png new file mode 100644 index 00000000..24a86250 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ng.png b/apps/36-blocks/src/assets/images/flags/ng.png new file mode 100644 index 00000000..04a539d1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ng.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ni.png b/apps/36-blocks/src/assets/images/flags/ni.png new file mode 100644 index 00000000..f44c209f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ni.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nl.png b/apps/36-blocks/src/assets/images/flags/nl.png new file mode 100644 index 00000000..5aee8428 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/no.png b/apps/36-blocks/src/assets/images/flags/no.png new file mode 100644 index 00000000..56062603 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/no.png differ diff --git a/apps/36-blocks/src/assets/images/flags/np.png b/apps/36-blocks/src/assets/images/flags/np.png new file mode 100644 index 00000000..b8757530 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/np.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nr.png b/apps/36-blocks/src/assets/images/flags/nr.png new file mode 100644 index 00000000..32094631 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nu.png b/apps/36-blocks/src/assets/images/flags/nu.png new file mode 100644 index 00000000..61a86e8d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/nz.png b/apps/36-blocks/src/assets/images/flags/nz.png new file mode 100644 index 00000000..90470ccd Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/nz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/om.png b/apps/36-blocks/src/assets/images/flags/om.png new file mode 100644 index 00000000..4da0e5a9 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/om.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pa.png b/apps/36-blocks/src/assets/images/flags/pa.png new file mode 100644 index 00000000..74b166d5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pa.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pe.png b/apps/36-blocks/src/assets/images/flags/pe.png new file mode 100644 index 00000000..c6660256 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pe.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pf.png b/apps/36-blocks/src/assets/images/flags/pf.png new file mode 100644 index 00000000..00dd2ca8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pg.png b/apps/36-blocks/src/assets/images/flags/pg.png new file mode 100644 index 00000000..dfa0bd56 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ph.png b/apps/36-blocks/src/assets/images/flags/ph.png new file mode 100644 index 00000000..4d7fc912 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ph.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pk.png b/apps/36-blocks/src/assets/images/flags/pk.png new file mode 100644 index 00000000..e38b53a5 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pl.png b/apps/36-blocks/src/assets/images/flags/pl.png new file mode 100644 index 00000000..943a6dd0 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pn.png b/apps/36-blocks/src/assets/images/flags/pn.png new file mode 100644 index 00000000..b1d4c2f7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pr.png b/apps/36-blocks/src/assets/images/flags/pr.png new file mode 100644 index 00000000..e76caefb Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ps.png b/apps/36-blocks/src/assets/images/flags/ps.png new file mode 100644 index 00000000..a7f3bb1f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ps.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pt.png b/apps/36-blocks/src/assets/images/flags/pt.png new file mode 100644 index 00000000..8f9b3dc2 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/pw.png b/apps/36-blocks/src/assets/images/flags/pw.png new file mode 100644 index 00000000..9e2d72d8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/pw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/py.png b/apps/36-blocks/src/assets/images/flags/py.png new file mode 100644 index 00000000..6fa4a041 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/py.png differ diff --git a/apps/36-blocks/src/assets/images/flags/qa.png b/apps/36-blocks/src/assets/images/flags/qa.png new file mode 100644 index 00000000..85c79938 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/qa.png differ diff --git a/apps/36-blocks/src/assets/images/flags/re.png b/apps/36-blocks/src/assets/images/flags/re.png new file mode 100644 index 00000000..04c53153 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/re.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ro.png b/apps/36-blocks/src/assets/images/flags/ro.png new file mode 100644 index 00000000..4abfb2c8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ro.png differ diff --git a/apps/36-blocks/src/assets/images/flags/rs.png b/apps/36-blocks/src/assets/images/flags/rs.png new file mode 100644 index 00000000..53993ae1 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/rs.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ru.png b/apps/36-blocks/src/assets/images/flags/ru.png new file mode 100644 index 00000000..6139dbc9 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ru.png differ diff --git a/apps/36-blocks/src/assets/images/flags/rw.png b/apps/36-blocks/src/assets/images/flags/rw.png new file mode 100644 index 00000000..5cade3ed Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/rw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sa.png b/apps/36-blocks/src/assets/images/flags/sa.png new file mode 100644 index 00000000..dc51076f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sa.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sb.png b/apps/36-blocks/src/assets/images/flags/sb.png new file mode 100644 index 00000000..31a9f154 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sb.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sc.png b/apps/36-blocks/src/assets/images/flags/sc.png new file mode 100644 index 00000000..88717b79 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sd.png b/apps/36-blocks/src/assets/images/flags/sd.png new file mode 100644 index 00000000..8058a314 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sd.png differ diff --git a/apps/36-blocks/src/assets/images/flags/se.png b/apps/36-blocks/src/assets/images/flags/se.png new file mode 100644 index 00000000..8173cf72 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/se.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sg.png b/apps/36-blocks/src/assets/images/flags/sg.png new file mode 100644 index 00000000..267e6419 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sh.png b/apps/36-blocks/src/assets/images/flags/sh.png new file mode 100644 index 00000000..067cae9e Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sh.png differ diff --git a/apps/36-blocks/src/assets/images/flags/si.png b/apps/36-blocks/src/assets/images/flags/si.png new file mode 100644 index 00000000..8a27e2ff Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/si.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sj.png b/apps/36-blocks/src/assets/images/flags/sj.png new file mode 100644 index 00000000..56062603 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sj.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sk.png b/apps/36-blocks/src/assets/images/flags/sk.png new file mode 100644 index 00000000..9258795d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sl.png b/apps/36-blocks/src/assets/images/flags/sl.png new file mode 100644 index 00000000..90341302 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sm.png b/apps/36-blocks/src/assets/images/flags/sm.png new file mode 100644 index 00000000..04afc0ae Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sn.png b/apps/36-blocks/src/assets/images/flags/sn.png new file mode 100644 index 00000000..4983ef78 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/so.png b/apps/36-blocks/src/assets/images/flags/so.png new file mode 100644 index 00000000..bfa58d00 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/so.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sr.png b/apps/36-blocks/src/assets/images/flags/sr.png new file mode 100644 index 00000000..846fe29f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ss.png b/apps/36-blocks/src/assets/images/flags/ss.png new file mode 100644 index 00000000..23231395 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ss.png differ diff --git a/apps/36-blocks/src/assets/images/flags/st.png b/apps/36-blocks/src/assets/images/flags/st.png new file mode 100644 index 00000000..f78178c8 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/st.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sv.png b/apps/36-blocks/src/assets/images/flags/sv.png new file mode 100644 index 00000000..82eb019f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sx.png b/apps/36-blocks/src/assets/images/flags/sx.png new file mode 100644 index 00000000..7c170b3c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sx.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sy.png b/apps/36-blocks/src/assets/images/flags/sy.png new file mode 100644 index 00000000..26c2935b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sy.png differ diff --git a/apps/36-blocks/src/assets/images/flags/sz.png b/apps/36-blocks/src/assets/images/flags/sz.png new file mode 100644 index 00000000..993ccfa4 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/sz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tc.png b/apps/36-blocks/src/assets/images/flags/tc.png new file mode 100644 index 00000000..0427a2d0 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/td.png b/apps/36-blocks/src/assets/images/flags/td.png new file mode 100644 index 00000000..db0dab08 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/td.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tf.png b/apps/36-blocks/src/assets/images/flags/tf.png new file mode 100644 index 00000000..34920dca Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tf.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tg.png b/apps/36-blocks/src/assets/images/flags/tg.png new file mode 100644 index 00000000..e7a8e8e7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/th.png b/apps/36-blocks/src/assets/images/flags/th.png new file mode 100644 index 00000000..dc580e44 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/th.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tj.png b/apps/36-blocks/src/assets/images/flags/tj.png new file mode 100644 index 00000000..3ca544a7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tj.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tk.png b/apps/36-blocks/src/assets/images/flags/tk.png new file mode 100644 index 00000000..1f8eda8b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tk.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tl.png b/apps/36-blocks/src/assets/images/flags/tl.png new file mode 100644 index 00000000..76a6eaa7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tl.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tm.png b/apps/36-blocks/src/assets/images/flags/tm.png new file mode 100644 index 00000000..aa768b81 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tn.png b/apps/36-blocks/src/assets/images/flags/tn.png new file mode 100644 index 00000000..638ef0b7 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/to.png b/apps/36-blocks/src/assets/images/flags/to.png new file mode 100644 index 00000000..bf01d8b4 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/to.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tr.png b/apps/36-blocks/src/assets/images/flags/tr.png new file mode 100644 index 00000000..73a0bb90 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tr.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tt.png b/apps/36-blocks/src/assets/images/flags/tt.png new file mode 100644 index 00000000..e7904e7b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tt.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tv.png b/apps/36-blocks/src/assets/images/flags/tv.png new file mode 100644 index 00000000..03d96a3f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tv.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tw.png b/apps/36-blocks/src/assets/images/flags/tw.png new file mode 100644 index 00000000..4a08f252 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tw.png differ diff --git a/apps/36-blocks/src/assets/images/flags/tz.png b/apps/36-blocks/src/assets/images/flags/tz.png new file mode 100644 index 00000000..1e2d3a79 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/tz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ua.png b/apps/36-blocks/src/assets/images/flags/ua.png new file mode 100644 index 00000000..03874040 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ua.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ug.png b/apps/36-blocks/src/assets/images/flags/ug.png new file mode 100644 index 00000000..ae1033ef Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ug.png differ diff --git a/apps/36-blocks/src/assets/images/flags/um.png b/apps/36-blocks/src/assets/images/flags/um.png new file mode 100644 index 00000000..058fd15c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/um.png differ diff --git a/apps/36-blocks/src/assets/images/flags/us.png b/apps/36-blocks/src/assets/images/flags/us.png new file mode 100644 index 00000000..058fd15c Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/us.png differ diff --git a/apps/36-blocks/src/assets/images/flags/uy.png b/apps/36-blocks/src/assets/images/flags/uy.png new file mode 100644 index 00000000..6226d59a Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/uy.png differ diff --git a/apps/36-blocks/src/assets/images/flags/uz.png b/apps/36-blocks/src/assets/images/flags/uz.png new file mode 100644 index 00000000..d173dd6f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/uz.png differ diff --git a/apps/36-blocks/src/assets/images/flags/va.png b/apps/36-blocks/src/assets/images/flags/va.png new file mode 100644 index 00000000..4132d67f Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/va.png differ diff --git a/apps/36-blocks/src/assets/images/flags/vc.png b/apps/36-blocks/src/assets/images/flags/vc.png new file mode 100644 index 00000000..14c8384d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/vc.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ve.png b/apps/36-blocks/src/assets/images/flags/ve.png new file mode 100644 index 00000000..a9ee5add Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ve.png differ diff --git a/apps/36-blocks/src/assets/images/flags/vg.png b/apps/36-blocks/src/assets/images/flags/vg.png new file mode 100644 index 00000000..3b5e3767 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/vg.png differ diff --git a/apps/36-blocks/src/assets/images/flags/vi.png b/apps/36-blocks/src/assets/images/flags/vi.png new file mode 100644 index 00000000..2b18144b Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/vi.png differ diff --git a/apps/36-blocks/src/assets/images/flags/vn.png b/apps/36-blocks/src/assets/images/flags/vn.png new file mode 100644 index 00000000..58f65991 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/vn.png differ diff --git a/apps/36-blocks/src/assets/images/flags/vu.png b/apps/36-blocks/src/assets/images/flags/vu.png new file mode 100644 index 00000000..406d3524 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/vu.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ws.png b/apps/36-blocks/src/assets/images/flags/ws.png new file mode 100644 index 00000000..c319d316 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ws.png differ diff --git a/apps/36-blocks/src/assets/images/flags/ye.png b/apps/36-blocks/src/assets/images/flags/ye.png new file mode 100644 index 00000000..eade987d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/ye.png differ diff --git a/apps/36-blocks/src/assets/images/flags/za.png b/apps/36-blocks/src/assets/images/flags/za.png new file mode 100644 index 00000000..eefe1afb Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/za.png differ diff --git a/apps/36-blocks/src/assets/images/flags/zm.png b/apps/36-blocks/src/assets/images/flags/zm.png new file mode 100644 index 00000000..b8d7f06d Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/zm.png differ diff --git a/apps/36-blocks/src/assets/images/flags/zw.png b/apps/36-blocks/src/assets/images/flags/zw.png new file mode 100644 index 00000000..b600fa84 Binary files /dev/null and b/apps/36-blocks/src/assets/images/flags/zw.png differ diff --git a/apps/shared/assets/utils/countries-info.ts b/apps/shared/assets/utils/countries-info.ts new file mode 100644 index 00000000..e52a5f97 --- /dev/null +++ b/apps/shared/assets/utils/countries-info.ts @@ -0,0 +1,2261 @@ +/** Interface for country data - simplified for use with Google libphonenumber */ +export interface Country { + /** Country name in English */ + name: string; + /** ISO 3166-1 alpha-2 country code */ + code: string; + /** International dialing code */ + dialCode: string; + /** Unicode flag emoji */ + flag: string; + /** Path to flag image */ + flagImage?: string; + /** Country name in native language */ + nativeName: string; + /** Realistic mobile number placeholder example (without country code) */ + placeholder?: string; +} +/** Comprehensive list of all countries with their telephone data */ +export const COUNTRIES_DATA: Country[] = [ + { + name: 'United States', + code: 'US', + dialCode: '+1', + flag: '🇺🇸', + flagImage: 'assets/images/flags/us.png', + nativeName: 'United States', + placeholder: '2015550123', + }, + { + name: 'United Kingdom', + code: 'GB', + dialCode: '+44', + flag: '🇬🇧', + flagImage: 'assets/images/flags/gb.png', + nativeName: 'United Kingdom', + placeholder: '07400123456', + }, + // A + { + name: 'Åland Islands', + code: 'AX', + dialCode: '+358', + flag: '🇦🇽', + flagImage: 'assets/images/flags/ax.png', + nativeName: 'Åland', + placeholder: '0401234567', + }, + { + name: 'Afghanistan', + code: 'AF', + dialCode: '+93', + flag: '🇦🇫', + flagImage: 'assets/images/flags/af.png', + nativeName: 'افغانستان', + placeholder: '0701234567', + }, + { + name: 'Albania', + code: 'AL', + dialCode: '+355', + flag: '🇦🇱', + flagImage: 'assets/images/flags/al.png', + nativeName: 'Shqipëria', + placeholder: '0671234567', + }, + { + name: 'Algeria', + code: 'DZ', + dialCode: '+213', + flag: '🇩🇿', + flagImage: 'assets/images/flags/dz.png', + nativeName: 'الجزائر', + placeholder: '0551234567', + }, + { + name: 'American Samoa', + code: 'AS', + dialCode: '+1684', + flag: '🇦🇸', + flagImage: 'assets/images/flags/as.png', + nativeName: 'Amerika Sāmoa', + placeholder: '6841234567', + }, + { + name: 'Andorra', + code: 'AD', + dialCode: '+376', + flag: '🇦🇩', + flagImage: 'assets/images/flags/ad.png', + nativeName: 'Andorra', + placeholder: '312345', + }, + { + name: 'Angola', + code: 'AO', + dialCode: '+244', + flag: '🇦🇴', + flagImage: 'assets/images/flags/ao.png', + nativeName: 'Angola', + placeholder: '923123456', + }, + { + name: 'Anguilla', + code: 'AI', + dialCode: '+1264', + flag: '🇦🇮', + flagImage: 'assets/images/flags/ai.png', + nativeName: 'Anguilla', + placeholder: '2642351234', + }, + { + name: 'Antigua and Barbuda', + code: 'AG', + dialCode: '+1268', + flag: '🇦🇬', + flagImage: 'assets/images/flags/ag.png', + nativeName: 'Antigua and Barbuda', + placeholder: '2687201234', + }, + { + name: 'Argentina', + code: 'AR', + dialCode: '+54', + flag: '🇦🇷', + flagImage: 'assets/images/flags/ar.png', + nativeName: 'Argentina', + placeholder: '1123456789', + }, + { + name: 'Armenia', + code: 'AM', + dialCode: '+374', + flag: '🇦🇲', + flagImage: 'assets/images/flags/am.png', + nativeName: 'Հայաստան', + placeholder: '077123456', + }, + { + name: 'Aruba', + code: 'AW', + dialCode: '+297', + flag: '🇦🇼', + flagImage: 'assets/images/flags/aw.png', + nativeName: 'Aruba', + placeholder: '5601234', + }, + { + name: 'Australia', + code: 'AU', + dialCode: '+61', + flag: '🇦🇺', + flagImage: 'assets/images/flags/au.png', + nativeName: 'Australia', + placeholder: '0412345678', + }, + { + name: 'Austria', + code: 'AT', + dialCode: '+43', + flag: '🇦🇹', + flagImage: 'assets/images/flags/at.png', + nativeName: 'Österreich', + placeholder: '06641234567', + }, + { + name: 'Azerbaijan', + code: 'AZ', + dialCode: '+994', + flag: '🇦🇿', + flagImage: 'assets/images/flags/az.png', + nativeName: 'Azərbaycan', + placeholder: '0401234567', + }, + // B + { + name: 'Bahamas', + code: 'BS', + dialCode: '+1242', + flag: '🇧🇸', + flagImage: 'assets/images/flags/bs.png', + nativeName: 'The Bahamas', + placeholder: '2423591234', + }, + { + name: 'Bahrain', + code: 'BH', + dialCode: '+973', + flag: '🇧🇭', + flagImage: 'assets/images/flags/bh.png', + nativeName: 'البحرين', + placeholder: '36001234', + }, + { + name: 'Bangladesh', + code: 'BD', + dialCode: '+880', + flag: '🇧🇩', + flagImage: 'assets/images/flags/bd.png', + nativeName: 'বাংলাদেশ', + placeholder: '01712345678', + }, + { + name: 'Barbados', + code: 'BB', + dialCode: '+1246', + flag: '🇧🇧', + flagImage: 'assets/images/flags/bb.png', + nativeName: 'Barbados', + placeholder: '2462501234', + }, + { + name: 'Belarus', + code: 'BY', + dialCode: '+375', + flag: '🇧🇾', + flagImage: 'assets/images/flags/by.png', + nativeName: 'Беларусь', + placeholder: '0291234567', + }, + { + name: 'Belgium', + code: 'BE', + dialCode: '+32', + flag: '🇧🇪', + flagImage: 'assets/images/flags/be.png', + nativeName: 'België / Belgique', + placeholder: '0470123456', + }, + { + name: 'Belize', + code: 'BZ', + dialCode: '+501', + flag: '🇧🇿', + flagImage: 'assets/images/flags/bz.png', + nativeName: 'Belize', + placeholder: '6221234', + }, + { + name: 'Benin', + code: 'BJ', + dialCode: '+229', + flag: '🇧🇯', + flagImage: 'assets/images/flags/bj.png', + nativeName: 'Bénin', + placeholder: '97123456', + }, + { + name: 'Bermuda', + code: 'BM', + dialCode: '+1441', + flag: '🇧🇲', + flagImage: 'assets/images/flags/bm.png', + nativeName: 'Bermuda', + placeholder: '4412921234', + }, + { + name: 'Bhutan', + code: 'BT', + dialCode: '+975', + flag: '🇧🇹', + flagImage: 'assets/images/flags/bt.png', + nativeName: 'འབྲུག', + placeholder: '17123456', + }, + { + name: 'Bolivia', + code: 'BO', + dialCode: '+591', + flag: '🇧🇴', + flagImage: 'assets/images/flags/bo.png', + nativeName: 'Bolivia', + placeholder: '71234567', + }, + { + name: 'Bosnia and Herzegovina', + code: 'BA', + dialCode: '+387', + flag: '🇧🇦', + flagImage: 'assets/images/flags/ba.png', + nativeName: 'Bosna i Hercegovina', + placeholder: '061123456', + }, + { + name: 'Botswana', + code: 'BW', + dialCode: '+267', + flag: '🇧🇼', + flagImage: 'assets/images/flags/bw.png', + nativeName: 'Botswana', + placeholder: '71123456', + }, + { + name: 'Brazil', + code: 'BR', + dialCode: '+55', + flag: '🇧🇷', + flagImage: 'assets/images/flags/br.png', + nativeName: 'Brasil', + placeholder: '11987654321', + }, + { + name: 'British Indian Ocean Territory', + code: 'IO', + dialCode: '+246', + flag: '🇮🇴', + flagImage: 'assets/images/flags/io.png', + nativeName: 'British Indian Ocean Territory', + placeholder: '3801401', + }, + { + name: 'British Virgin Islands', + code: 'VG', + dialCode: '+1284', + flag: '🇻🇬', + flagImage: 'assets/images/flags/vg.png', + nativeName: 'British Virgin Islands', + placeholder: '2843001234', + }, + { + name: 'Brunei', + code: 'BN', + dialCode: '+673', + flag: '🇧🇳', + flagImage: 'assets/images/flags/bn.png', + nativeName: 'Brunei Darussalam', + placeholder: '7121234', + }, + { + name: 'Bulgaria', + code: 'BG', + dialCode: '+359', + flag: '🇧🇬', + flagImage: 'assets/images/flags/bg.png', + nativeName: 'България', + placeholder: '0871234567', + }, + { + name: 'Burkina Faso', + code: 'BF', + dialCode: '+226', + flag: '🇧🇫', + flagImage: 'assets/images/flags/bf.png', + nativeName: 'Burkina Faso', + placeholder: '70123456', + }, + { + name: 'Burundi', + code: 'BI', + dialCode: '+257', + flag: '🇧🇮', + flagImage: 'assets/images/flags/bi.png', + nativeName: 'Burundi', + placeholder: '79561234', + }, + // C + { + name: 'Cambodia', + code: 'KH', + dialCode: '+855', + flag: '🇰🇭', + flagImage: 'assets/images/flags/kh.png', + nativeName: 'កម្ពុជា', + placeholder: '012345678', + }, + { + name: 'Cameroon', + code: 'CM', + dialCode: '+237', + flag: '🇨🇲', + flagImage: 'assets/images/flags/cm.png', + nativeName: 'Cameroun', + placeholder: '671234567', + }, + { + name: 'Canada', + code: 'CA', + dialCode: '+1', + flag: '🇨🇦', + flagImage: 'assets/images/flags/ca.png', + nativeName: 'Canada', + placeholder: '4165551234', + }, + { + name: 'Cape Verde', + code: 'CV', + dialCode: '+238', + flag: '🇨🇻', + flagImage: 'assets/images/flags/cv.png', + nativeName: 'Cabo Verde', + placeholder: '9911234', + }, + { + name: 'Caribbean Netherlands', + code: 'BQ', + dialCode: '+599', + flag: '🇧🇶', + flagImage: 'assets/images/flags/bq.png', + nativeName: 'Caribbean Netherlands', + }, + { + name: 'Cayman Islands', + code: 'KY', + dialCode: '+1345', + flag: '🇰🇾', + flagImage: 'assets/images/flags/ky.png', + nativeName: 'Cayman Islands', + placeholder: '3453231234', + }, + { + name: 'Central African Republic', + code: 'CF', + dialCode: '+236', + flag: '🇨🇫', + flagImage: 'assets/images/flags/cf.png', + nativeName: 'République Centrafricaine', + placeholder: '72001234', + }, + { + name: 'Chad', + code: 'TD', + dialCode: '+235', + flag: '🇹🇩', + flagImage: 'assets/images/flags/td.png', + nativeName: 'تشاد', + placeholder: '63012345', + }, + { + name: 'Chile', + code: 'CL', + dialCode: '+56', + flag: '🇨🇱', + flagImage: 'assets/images/flags/cl.png', + nativeName: 'Chile', + placeholder: '912345678', + }, + { + name: 'China', + code: 'CN', + dialCode: '+86', + flag: '🇨🇳', + flagImage: 'assets/images/flags/cn.png', + nativeName: '中国', + placeholder: '13800138000', + }, + { + name: 'Christmas Island', + code: 'CX', + dialCode: '+61', + flag: '🇨🇽', + flagImage: 'assets/images/flags/cx.png', + nativeName: 'Christmas Island', + placeholder: '0412345678', + }, + { + name: 'Cocos (Keeling) Islands', + code: 'CC', + dialCode: '+61', + flag: '🇨🇨', + flagImage: 'assets/images/flags/cc.png', + nativeName: 'Cocos (Keeling) Islands', + placeholder: '0412345678', + }, + { + name: 'Colombia', + code: 'CO', + dialCode: '+57', + flag: '🇨🇴', + flagImage: 'assets/images/flags/co.png', + nativeName: 'Colombia', + placeholder: '3001234567', + }, + { + name: 'Comoros', + code: 'KM', + dialCode: '+269', + flag: '🇰🇲', + flagImage: 'assets/images/flags/km.png', + nativeName: 'Komori', + placeholder: '3211234', + }, + { + name: 'Congo', + code: 'CG', + dialCode: '+242', + flag: '🇨🇬', + flagImage: 'assets/images/flags/cg.png', + nativeName: 'Congo', + placeholder: '061234567', + }, + { + name: 'Democratic Republic of the Congo', + code: 'CD', + dialCode: '+243', + flag: '🇨🇩', + flagImage: 'assets/images/flags/cd.png', + nativeName: 'République Démocratique du Congo', + placeholder: '0991234567', + }, + { + name: 'Cook Islands', + code: 'CK', + dialCode: '+682', + flag: '🇨🇰', + flagImage: 'assets/images/flags/ck.png', + nativeName: 'Cook Islands', + placeholder: '71234', + }, + { + name: 'Costa Rica', + code: 'CR', + dialCode: '+506', + flag: '🇨🇷', + flagImage: 'assets/images/flags/cr.png', + nativeName: 'Costa Rica', + placeholder: '83123456', + }, + { + name: 'Croatia', + code: 'HR', + dialCode: '+385', + flag: '🇭🇷', + flagImage: 'assets/images/flags/hr.png', + nativeName: 'Hrvatska', + placeholder: '0912345678', + }, + { + name: 'Cuba', + code: 'CU', + dialCode: '+53', + flag: '🇨🇺', + flagImage: 'assets/images/flags/cu.png', + nativeName: 'Cuba', + placeholder: '051234567', + }, + { + name: 'Curaçao', + code: 'CW', + dialCode: '+599', + flag: '🇨🇼', + flagImage: 'assets/images/flags/cw.png', + nativeName: 'Curaçao', + placeholder: '95512345', + }, + { + name: 'Cyprus', + code: 'CY', + dialCode: '+357', + flag: '🇨🇾', + flagImage: 'assets/images/flags/cy.png', + nativeName: 'Κύπρος', + placeholder: '96123456', + }, + { + name: 'Czech Republic', + code: 'CZ', + dialCode: '+420', + flag: '🇨🇿', + flagImage: 'assets/images/flags/cz.png', + nativeName: 'Česká republika', + placeholder: '601234567', + }, + // D + { + name: 'Denmark', + code: 'DK', + dialCode: '+45', + flag: '🇩🇰', + flagImage: 'assets/images/flags/dk.png', + nativeName: 'Danmark', + placeholder: '20123456', + }, + { + name: 'Djibouti', + code: 'DJ', + dialCode: '+253', + flag: '🇩🇯', + flagImage: 'assets/images/flags/dj.png', + nativeName: 'Djibouti', + placeholder: '77831001', + }, + { + name: 'Dominica', + code: 'DM', + dialCode: '+1767', + flag: '🇩🇲', + flagImage: 'assets/images/flags/dm.png', + nativeName: 'Dominica', + placeholder: '7672251234', + }, + { + name: 'Dominican Republic', + code: 'DO', + dialCode: '+1809', + flag: '🇩🇴', + flagImage: 'assets/images/flags/do.png', + nativeName: 'República Dominicana', + placeholder: '8091234567', + }, + // E + { + name: 'Ecuador', + code: 'EC', + dialCode: '+593', + flag: '🇪🇨', + flagImage: 'assets/images/flags/ec.png', + nativeName: 'Ecuador', + placeholder: '0991234567', + }, + { + name: 'Egypt', + code: 'EG', + dialCode: '+20', + flag: '🇪🇬', + flagImage: 'assets/images/flags/eg.png', + nativeName: 'مصر', + placeholder: '01001234567', + }, + { + name: 'El Salvador', + code: 'SV', + dialCode: '+503', + flag: '🇸🇻', + flagImage: 'assets/images/flags/sv.png', + nativeName: 'El Salvador', + placeholder: '70123456', + }, + { + name: 'Equatorial Guinea', + code: 'GQ', + dialCode: '+240', + flag: '🇬🇶', + flagImage: 'assets/images/flags/gq.png', + nativeName: 'Guinea Ecuatorial', + placeholder: '222123456', + }, + { + name: 'Eritrea', + code: 'ER', + dialCode: '+291', + flag: '🇪🇷', + flagImage: 'assets/images/flags/er.png', + nativeName: 'ኤርትራ', + placeholder: '07123456', + }, + { + name: 'Estonia', + code: 'EE', + dialCode: '+372', + flag: '🇪🇪', + flagImage: 'assets/images/flags/ee.png', + nativeName: 'Eesti', + placeholder: '51234567', + }, + { + name: 'Eswatini', + code: 'SZ', + dialCode: '+268', + flag: '🇸🇿', + flagImage: 'assets/images/flags/sz.png', + nativeName: 'Eswatini', + placeholder: '76123456', + }, + { + name: 'Ethiopia', + code: 'ET', + dialCode: '+251', + flag: '🇪🇹', + flagImage: 'assets/images/flags/et.png', + nativeName: 'ኢትዮጵያ', + placeholder: '0911234567', + }, + // F + { + name: 'Falkland Islands', + code: 'FK', + dialCode: '+500', + flag: '🇫🇰', + flagImage: 'assets/images/flags/fk.png', + nativeName: 'Falkland Islands', + placeholder: '51234', + }, + { + name: 'Faroe Islands', + code: 'FO', + dialCode: '+298', + flag: '🇫🇴', + flagImage: 'assets/images/flags/fo.png', + nativeName: 'Føroyar', + placeholder: '211234', + }, + { + name: 'Fiji', + code: 'FJ', + dialCode: '+679', + flag: '🇫🇯', + flagImage: 'assets/images/flags/fj.png', + nativeName: 'Fiji', + placeholder: '7012345', + }, + { + name: 'Finland', + code: 'FI', + dialCode: '+358', + flag: '🇫🇮', + flagImage: 'assets/images/flags/fi.png', + nativeName: 'Suomi', + placeholder: '0401234567', + }, + { + name: 'France', + code: 'FR', + dialCode: '+33', + flag: '🇫🇷', + flagImage: 'assets/images/flags/fr.png', + nativeName: 'France', + placeholder: '0612345678', + }, + { + name: 'French Guiana', + code: 'GF', + dialCode: '+594', + flag: '🇬🇫', + flagImage: 'assets/images/flags/gf.png', + nativeName: 'Guyane française', + placeholder: '0694201234', + }, + { + name: 'French Polynesia', + code: 'PF', + dialCode: '+689', + flag: '🇵🇫', + flagImage: 'assets/images/flags/pf.png', + nativeName: 'Polynésie française', + placeholder: '87123456', + }, + // G + { + name: 'Gabon', + code: 'GA', + dialCode: '+241', + flag: '🇬🇦', + flagImage: 'assets/images/flags/ga.png', + nativeName: 'Gabon', + placeholder: '06031234', + }, + { + name: 'Gambia', + code: 'GM', + dialCode: '+220', + flag: '🇬🇲', + flagImage: 'assets/images/flags/gm.png', + nativeName: 'Gambia', + placeholder: '3012345', + }, + { + name: 'Georgia', + code: 'GE', + dialCode: '+995', + flag: '🇬🇪', + flagImage: 'assets/images/flags/ge.png', + nativeName: 'საქართველო', + placeholder: '555123456', + }, + { + name: 'Germany', + code: 'DE', + dialCode: '+49', + flag: '🇩🇪', + flagImage: 'assets/images/flags/de.png', + nativeName: 'Deutschland', + placeholder: '01512345678', + }, + { + name: 'Ghana', + code: 'GH', + dialCode: '+233', + flag: '🇬🇭', + flagImage: 'assets/images/flags/gh.png', + nativeName: 'Ghana', + placeholder: '0241234567', + }, + { + name: 'Gibraltar', + code: 'GI', + dialCode: '+350', + flag: '🇬🇮', + flagImage: 'assets/images/flags/gi.png', + nativeName: 'Gibraltar', + placeholder: '57123456', + }, + { + name: 'Greece', + code: 'GR', + dialCode: '+30', + flag: '🇬🇷', + flagImage: 'assets/images/flags/gr.png', + nativeName: 'Ελλάδα', + placeholder: '6912345678', + }, + { + name: 'Greenland', + code: 'GL', + dialCode: '+299', + flag: '🇬🇱', + flagImage: 'assets/images/flags/gl.png', + nativeName: 'Kalaallit Nunaat', + placeholder: '321234', + }, + { + name: 'Grenada', + code: 'GD', + dialCode: '+1473', + flag: '🇬🇩', + flagImage: 'assets/images/flags/gd.png', + nativeName: 'Grenada', + placeholder: '4734031234', + }, + { + name: 'Guadeloupe', + code: 'GP', + dialCode: '+590', + flag: '🇬🇵', + flagImage: 'assets/images/flags/gp.png', + nativeName: 'Guadeloupe', + placeholder: '0690001234', + }, + { + name: 'Guam', + code: 'GU', + dialCode: '+1671', + flag: '🇬🇺', + flagImage: 'assets/images/flags/gu.png', + nativeName: 'Guåhan', + placeholder: '6713001234', + }, + { + name: 'Guatemala', + code: 'GT', + dialCode: '+502', + flag: '🇬🇹', + flagImage: 'assets/images/flags/gt.png', + nativeName: 'Guatemala', + placeholder: '51234567', + }, + { + name: 'Guernsey', + code: 'GG', + dialCode: '+44', + flag: '🇬🇬', + flagImage: 'assets/images/flags/gg.png', + nativeName: 'Guernsey', + placeholder: '07781123456', + }, + { + name: 'Guinea', + code: 'GN', + dialCode: '+224', + flag: '🇬🇳', + flagImage: 'assets/images/flags/gn.png', + nativeName: 'Guinée', + placeholder: '601123456', + }, + { + name: 'Guinea-Bissau', + code: 'GW', + dialCode: '+245', + flag: '🇬🇼', + flagImage: 'assets/images/flags/gw.png', + nativeName: 'Guiné-Bissau', + placeholder: '955012345', + }, + { + name: 'Guyana', + code: 'GY', + dialCode: '+592', + flag: '🇬🇾', + flagImage: 'assets/images/flags/gy.png', + nativeName: 'Guyana', + placeholder: '6091234567', + }, + // H + { + name: 'Haiti', + code: 'HT', + dialCode: '+509', + flag: '🇭🇹', + flagImage: 'assets/images/flags/ht.png', + nativeName: 'Haïti', + placeholder: '34101234', + }, + { + name: 'Honduras', + code: 'HN', + dialCode: '+504', + flag: '🇭🇳', + flagImage: 'assets/images/flags/hn.png', + nativeName: 'Honduras', + placeholder: '91234567', + }, + { + name: 'Hong Kong', + code: 'HK', + dialCode: '+852', + flag: '🇭🇰', + flagImage: 'assets/images/flags/hk.png', + nativeName: '香港', + placeholder: '51234567', + }, + { + name: 'Hungary', + code: 'HU', + dialCode: '+36', + flag: '🇭🇺', + flagImage: 'assets/images/flags/hu.png', + nativeName: 'Magyarország', + placeholder: '301234567', + }, + // I + { + name: 'Iceland', + code: 'IS', + dialCode: '+354', + flag: '🇮🇸', + flagImage: 'assets/images/flags/is.png', + nativeName: 'Ísland', + placeholder: '6111234', + }, + { + name: 'India', + code: 'IN', + dialCode: '+91', + flag: '🇮🇳', + flagImage: 'assets/images/flags/in.png', + nativeName: 'भारत', + placeholder: '9876543210', + }, + { + name: 'Indonesia', + code: 'ID', + dialCode: '+62', + flag: '🇮🇩', + flagImage: 'assets/images/flags/id.png', + nativeName: 'Indonesia', + placeholder: '081234567890', + }, + { + name: 'Iran', + code: 'IR', + dialCode: '+98', + flag: '🇮🇷', + flagImage: 'assets/images/flags/ir.png', + nativeName: 'ایران', + placeholder: '09121234567', + }, + { + name: 'Iraq', + code: 'IQ', + dialCode: '+964', + flag: '🇮🇶', + flagImage: 'assets/images/flags/iq.png', + nativeName: 'العراق', + placeholder: '07901234567', + }, + { + name: 'Ireland', + code: 'IE', + dialCode: '+353', + flag: '🇮🇪', + flagImage: 'assets/images/flags/ie.png', + nativeName: 'Éire', + placeholder: '0871234567', + }, + { + name: 'Isle of Man', + code: 'IM', + dialCode: '+44', + flag: '🇮🇲', + flagImage: 'assets/images/flags/im.png', + nativeName: 'Isle of Man', + placeholder: '07924123456', + }, + { + name: 'Israel', + code: 'IL', + dialCode: '+972', + flag: '🇮🇱', + flagImage: 'assets/images/flags/il.png', + nativeName: 'ישראל', + placeholder: '0501234567', + }, + { + name: 'Italy', + code: 'IT', + dialCode: '+39', + flag: '🇮🇹', + flagImage: 'assets/images/flags/it.png', + nativeName: 'Italia', + placeholder: '3123456789', + }, + { + name: 'Ivory Coast', + code: 'CI', + dialCode: '+225', + flag: '🇨🇮', + flagImage: 'assets/images/flags/ci.png', + nativeName: "Côte d'Ivoire", + }, + // J + { + name: 'Jamaica', + code: 'JM', + dialCode: '+1876', + flag: '🇯🇲', + flagImage: 'assets/images/flags/jm.png', + nativeName: 'Jamaica', + placeholder: '8762101234', + }, + { + name: 'Japan', + code: 'JP', + dialCode: '+81', + flag: '🇯🇵', + flagImage: 'assets/images/flags/jp.png', + nativeName: '日本', + placeholder: '09012345678', + }, + { + name: 'Jersey', + code: 'JE', + dialCode: '+44', + flag: '🇯🇪', + flagImage: 'assets/images/flags/je.png', + nativeName: 'Jersey', + placeholder: '07797712345', + }, + { + name: 'Jordan', + code: 'JO', + dialCode: '+962', + flag: '🇯🇴', + flagImage: 'assets/images/flags/jo.png', + nativeName: 'الأردن', + placeholder: '0791234567', + }, + // K + { + name: 'Kazakhstan', + code: 'KZ', + dialCode: '+7', + flag: '🇰🇿', + flagImage: 'assets/images/flags/kz.png', + nativeName: 'Қазақстан', + placeholder: '7071234567', + }, + { + name: 'Kenya', + code: 'KE', + dialCode: '+254', + flag: '🇰🇪', + flagImage: 'assets/images/flags/ke.png', + nativeName: 'Kenya', + placeholder: '0712345678', + }, + { + name: 'Kiribati', + code: 'KI', + dialCode: '+686', + flag: '🇰🇮', + flagImage: 'assets/images/flags/ki.png', + nativeName: 'Kiribati', + placeholder: '72001234', + }, + { + name: 'Kosovo', + code: 'XK', + dialCode: '+383', + flag: '🇽🇰', + flagImage: '', // No flag image available for Kosovo (XK) + nativeName: 'Kosovë', + placeholder: '044123456', + }, + { + name: 'Kuwait', + code: 'KW', + dialCode: '+965', + flag: '🇰🇼', + flagImage: 'assets/images/flags/kw.png', + nativeName: 'الكويت', + placeholder: '51234567', + }, + { + name: 'Kyrgyzstan', + code: 'KG', + dialCode: '+996', + flag: '🇰🇬', + flagImage: 'assets/images/flags/kg.png', + nativeName: 'Кыргызстан', + placeholder: '0700123456', + }, + // L + { + name: 'Laos', + code: 'LA', + dialCode: '+856', + flag: '🇱🇦', + flagImage: 'assets/images/flags/la.png', + nativeName: 'ລາວ', + placeholder: '020234567', + }, + { + name: 'Latvia', + code: 'LV', + dialCode: '+371', + flag: '🇱🇻', + flagImage: 'assets/images/flags/lv.png', + nativeName: 'Latvija', + placeholder: '21234567', + }, + { + name: 'Lebanon', + code: 'LB', + dialCode: '+961', + flag: '🇱🇧', + flagImage: 'assets/images/flags/lb.png', + nativeName: 'لبنان', + placeholder: '71123456', + }, + { + name: 'Lesotho', + code: 'LS', + dialCode: '+266', + flag: '🇱🇸', + flagImage: 'assets/images/flags/ls.png', + nativeName: 'Lesotho', + placeholder: '50123456', + }, + { + name: 'Liberia', + code: 'LR', + dialCode: '+231', + flag: '🇱🇷', + flagImage: 'assets/images/flags/lr.png', + nativeName: 'Liberia', + placeholder: '0770123456', + }, + { + name: 'Libya', + code: 'LY', + dialCode: '+218', + flag: '🇱🇾', + flagImage: 'assets/images/flags/ly.png', + nativeName: 'ليبيا', + placeholder: '0912345678', + }, + { + name: 'Liechtenstein', + code: 'LI', + dialCode: '+423', + flag: '🇱🇮', + flagImage: 'assets/images/flags/li.png', + nativeName: 'Liechtenstein', + placeholder: '660234567', + }, + { + name: 'Lithuania', + code: 'LT', + dialCode: '+370', + flag: '🇱🇹', + flagImage: 'assets/images/flags/lt.png', + nativeName: 'Lietuva', + placeholder: '61234567', + }, + { + name: 'Luxembourg', + code: 'LU', + dialCode: '+352', + flag: '🇱🇺', + flagImage: 'assets/images/flags/lu.png', + nativeName: 'Lëtzebuerg', + placeholder: '621123456', + }, + // M + { + name: 'Macau', + code: 'MO', + dialCode: '+853', + flag: '🇲🇴', + flagImage: 'assets/images/flags/mo.png', + nativeName: '澳門', + placeholder: '66123456', + }, + { + name: 'Madagascar', + code: 'MG', + dialCode: '+261', + flag: '🇲🇬', + flagImage: 'assets/images/flags/mg.png', + nativeName: 'Madagasikara', + placeholder: '321234567', + }, + { + name: 'Malawi', + code: 'MW', + dialCode: '+265', + flag: '🇲🇼', + flagImage: 'assets/images/flags/mw.png', + nativeName: 'Malawi', + placeholder: '0991234567', + }, + { + name: 'Malaysia', + code: 'MY', + dialCode: '+60', + flag: '🇲🇾', + flagImage: 'assets/images/flags/my.png', + nativeName: 'Malaysia', + placeholder: '0123456789', + }, + { + name: 'Maldives', + code: 'MV', + dialCode: '+960', + flag: '🇲🇻', + flagImage: 'assets/images/flags/mv.png', + nativeName: 'ދިވެހިބަސް', + placeholder: '7771234', + }, + { + name: 'Mali', + code: 'ML', + dialCode: '+223', + flag: '🇲🇱', + flagImage: 'assets/images/flags/ml.png', + nativeName: 'Mali', + placeholder: '65012345', + }, + { + name: 'Malta', + code: 'MT', + dialCode: '+356', + flag: '🇲🇹', + flagImage: 'assets/images/flags/mt.png', + nativeName: 'Malta', + placeholder: '99123456', + }, + { + name: 'Marshall Islands', + code: 'MH', + dialCode: '+692', + flag: '🇲🇭', + flagImage: 'assets/images/flags/mh.png', + nativeName: 'Marshall Islands', + placeholder: '2351234', + }, + { + name: 'Martinique', + code: 'MQ', + dialCode: '+596', + flag: '🇲🇶', + flagImage: 'assets/images/flags/mq.png', + nativeName: 'Martinique', + placeholder: '0696201234', + }, + { + name: 'Mauritania', + code: 'MR', + dialCode: '+222', + flag: '🇲🇷', + flagImage: 'assets/images/flags/mr.png', + nativeName: 'موريتانيا', + placeholder: '22123456', + }, + { + name: 'Mauritius', + code: 'MU', + dialCode: '+230', + flag: '🇲🇺', + flagImage: 'assets/images/flags/mu.png', + nativeName: 'Maurice', + placeholder: '52512345', + }, + { + name: 'Mayotte', + code: 'YT', + dialCode: '+262', + flag: '🇫🇷', + flagImage: 'assets/images/flags/fr.png', + nativeName: 'Mayotte', + placeholder: '0639012345', + }, + { + name: 'Mexico', + code: 'MX', + dialCode: '+52', + flag: '🇲🇽', + flagImage: 'assets/images/flags/mx.png', + nativeName: 'México', + placeholder: '5512345678', + }, + { + name: 'Micronesia', + code: 'FM', + dialCode: '+691', + flag: '🇫🇲', + flagImage: 'assets/images/flags/fm.png', + nativeName: 'Micronesia', + placeholder: '3501234', + }, + { + name: 'Moldova', + code: 'MD', + dialCode: '+373', + flag: '🇲🇩', + flagImage: 'assets/images/flags/md.png', + nativeName: 'Republica Moldova', + placeholder: '0621234567', + }, + { + name: 'Monaco', + code: 'MC', + dialCode: '+377', + flag: '🇲🇨', + flagImage: 'assets/images/flags/mc.png', + nativeName: 'Monaco', + placeholder: '0612345678', + }, + { + name: 'Mongolia', + code: 'MN', + dialCode: '+976', + flag: '🇲🇳', + flagImage: 'assets/images/flags/mn.png', + nativeName: 'Монгол', + placeholder: '88123456', + }, + { + name: 'Montenegro', + code: 'ME', + dialCode: '+382', + flag: '🇲🇪', + flagImage: 'assets/images/flags/me.png', + nativeName: 'Crna Gora', + placeholder: '067123456', + }, + { + name: 'Montserrat', + code: 'MS', + dialCode: '+1664', + flag: '🇲🇸', + flagImage: 'assets/images/flags/ms.png', + nativeName: 'Montserrat', + placeholder: '6644913456', + }, + { + name: 'Morocco', + code: 'MA', + dialCode: '+212', + flag: '🇲🇦', + flagImage: 'assets/images/flags/ma.png', + nativeName: 'المغرب', + placeholder: '0612345678', + }, + { + name: 'Mozambique', + code: 'MZ', + dialCode: '+258', + flag: '🇲🇿', + flagImage: 'assets/images/flags/mz.png', + nativeName: 'Moçambique', + placeholder: '821234567', + }, + { + name: 'Myanmar', + code: 'MM', + dialCode: '+95', + flag: '🇲🇲', + flagImage: 'assets/images/flags/mm.png', + nativeName: 'မြန်မာ', + placeholder: '09212345678', + }, + // N + { + name: 'Namibia', + code: 'NA', + dialCode: '+264', + flag: '🇳🇦', + flagImage: 'assets/images/flags/na.png', + nativeName: 'Namibië', + placeholder: '0811234567', + }, + { + name: 'Nauru', + code: 'NR', + dialCode: '+674', + flag: '🇳🇷', + flagImage: 'assets/images/flags/nr.png', + nativeName: 'Nauru', + placeholder: '5551234', + }, + { + name: 'Nepal', + code: 'NP', + dialCode: '+977', + flag: '🇳🇵', + flagImage: 'assets/images/flags/np.png', + nativeName: 'नेपाल', + placeholder: '9841234567', + }, + { + name: 'Netherlands', + code: 'NL', + dialCode: '+31', + flag: '🇳🇱', + flagImage: 'assets/images/flags/nl.png', + nativeName: 'Nederland', + placeholder: '0612345678', + }, + { + name: 'New Caledonia', + code: 'NC', + dialCode: '+687', + flag: '🇳🇨', + flagImage: 'assets/images/flags/nc.png', + nativeName: 'Nouvelle-Calédonie', + placeholder: '751234', + }, + { + name: 'New Zealand', + code: 'NZ', + dialCode: '+64', + flag: '🇳🇿', + flagImage: 'assets/images/flags/nz.png', + nativeName: 'New Zealand', + placeholder: '0212345678', + }, + { + name: 'Nicaragua', + code: 'NI', + dialCode: '+505', + flag: '🇳🇮', + flagImage: 'assets/images/flags/ni.png', + nativeName: 'Nicaragua', + placeholder: '81234567', + }, + { + name: 'Niger', + code: 'NE', + dialCode: '+227', + flag: '🇳🇪', + flagImage: 'assets/images/flags/ne.png', + nativeName: 'Nijar', + placeholder: '93123456', + }, + { + name: 'Nigeria', + code: 'NG', + dialCode: '+234', + flag: '🇳🇬', + flagImage: 'assets/images/flags/ng.png', + nativeName: 'Nigeria', + placeholder: '08012345678', + }, + { + name: 'Niue', + code: 'NU', + dialCode: '+683', + flag: '🇳🇺', + flagImage: 'assets/images/flags/nu.png', + nativeName: 'Niue', + placeholder: '1234', + }, + { + name: 'Norfolk Island', + code: 'NF', + dialCode: '+672', + flag: '🇳🇫', + flagImage: 'assets/images/flags/nf.png', + nativeName: 'Norfolk Island', + placeholder: '381234', + }, + { + name: 'North Korea', + code: 'KP', + dialCode: '+850', + flag: '🇰🇵', + flagImage: 'assets/images/flags/kp.png', + nativeName: '조선 민주주의 인민 공화국', + placeholder: '01921234567', + }, + { + name: 'North Macedonia', + code: 'MK', + dialCode: '+389', + flag: '🇲🇰', + flagImage: 'assets/images/flags/mk.png', + nativeName: '+389', + placeholder: '070234567', + }, + { + name: 'Northern Mariana Islands', + code: 'MP', + dialCode: '+1670', + flag: '🇲🇵', + flagImage: 'assets/images/flags/mp.png', + nativeName: 'Northern Mariana Islands', + placeholder: '6702352345', + }, + { + name: 'Norway', + code: 'NO', + dialCode: '+47', + flag: '🇳🇴', + flagImage: 'assets/images/flags/no.png', + nativeName: 'Norge', + placeholder: '40123456', + }, + // O + { + name: 'Oman', + code: 'OM', + dialCode: '+968', + flag: '🇴🇲', + flagImage: 'assets/images/flags/om.png', + nativeName: 'عُمان', + placeholder: '92123456', + }, + // P + { + name: 'Pakistan', + code: 'PK', + dialCode: '+92', + flag: '🇵🇰', + flagImage: 'assets/images/flags/pk.png', + nativeName: 'پاکستان', + placeholder: '03001234567', + }, + { + name: 'Palau', + code: 'PW', + dialCode: '+680', + flag: '🇵🇼', + flagImage: 'assets/images/flags/pw.png', + nativeName: 'Palau', + placeholder: '7701234', + }, + { + name: 'Palestine', + code: 'PS', + dialCode: '+970', + flag: '🇵🇸', + flagImage: 'assets/images/flags/ps.png', + nativeName: 'فلسطين', + placeholder: '0599123456', + }, + { + name: 'Panama', + code: 'PA', + dialCode: '+507', + flag: '🇵🇦', + flagImage: 'assets/images/flags/pa.png', + nativeName: 'Panamá', + placeholder: '61234567', + }, + { + name: 'Papua New Guinea', + code: 'PG', + dialCode: '+675', + flag: '🇵🇬', + flagImage: 'assets/images/flags/pg.png', + nativeName: 'Papua New Guinea', + placeholder: '70123456', + }, + { + name: 'Paraguay', + code: 'PY', + dialCode: '+595', + flag: '🇵🇾', + flagImage: 'assets/images/flags/py.png', + nativeName: 'Paraguay', + placeholder: '0961234567', + }, + { + name: 'Peru', + code: 'PE', + dialCode: '+51', + flag: '🇵🇪', + flagImage: 'assets/images/flags/pe.png', + nativeName: 'Perú', + placeholder: '987654321', + }, + { + name: 'Philippines', + code: 'PH', + dialCode: '+63', + flag: '🇵🇭', + flagImage: 'assets/images/flags/ph.png', + nativeName: 'Philippines', + placeholder: '09171234567', + }, + { + name: 'Pitcairn', + code: 'PN', + dialCode: '+64', + flag: '🇵🇳', + flagImage: 'assets/images/flags/pn.png', + nativeName: 'Pitcairn Islands', + }, + { + name: 'Poland', + code: 'PL', + dialCode: '+48', + flag: '🇵🇱', + flagImage: 'assets/images/flags/pl.png', + nativeName: 'Polska', + placeholder: '501234567', + }, + { + name: 'Portugal', + code: 'PT', + dialCode: '+351', + flag: '🇵🇹', + flagImage: 'assets/images/flags/pt.png', + nativeName: 'Portugal', + placeholder: '912345678', + }, + { + name: 'Puerto Rico', + code: 'PR', + dialCode: '+1', + flag: '🇵🇷', + flagImage: 'assets/images/flags/pr.png', + nativeName: 'Puerto Rico', + placeholder: '7872345678', + }, + // Q + { + name: 'Qatar', + code: 'QA', + dialCode: '+974', + flag: '🇶🇦', + flagImage: 'assets/images/flags/qa.png', + nativeName: 'قطر', + placeholder: '33123456', + }, + // R + { + name: 'Réunion', + code: 'RE', + dialCode: '+262', + flag: '🇫🇷', + flagImage: 'assets/images/flags/mf.png', + nativeName: 'La Réunion', + placeholder: '0692123456', + }, + { + name: 'Romania', + code: 'RO', + dialCode: '+40', + flag: '🇷🇴', + flagImage: 'assets/images/flags/ro.png', + nativeName: 'România', + placeholder: '0712345678', + }, + { + name: 'Russia', + code: 'RU', + dialCode: '+7', + flag: '🇷🇺', + flagImage: 'assets/images/flags/ru.png', + nativeName: 'Россия', + placeholder: '9123456789', + }, + { + name: 'Rwanda', + code: 'RW', + dialCode: '+250', + flag: '🇷🇼', + flagImage: 'assets/images/flags/rw.png', + nativeName: 'Rwanda', + placeholder: '0781234567', + }, + // S + { + name: 'Saint Barthélemy', + code: 'BL', + dialCode: '+590', + flag: '🇫🇷', + flagImage: 'assets/images/flags/fr.png', + nativeName: 'Saint-Barthélemy', + placeholder: '0690001234', + }, + { + name: 'Saint Helena', + code: 'SH', + dialCode: '+290', + flag: '🇸🇭', + flagImage: 'assets/images/flags/sh.png', + nativeName: 'Saint Helena', + placeholder: '62158', + }, + { + name: 'Saint Kitts and Nevis', + code: 'KN', + dialCode: '+1869', + flag: '🇰🇳', + flagImage: 'assets/images/flags/kn.png', + nativeName: 'Saint Kitts and Nevis', + placeholder: '8694651234', + }, + { + name: 'Saint Lucia', + code: 'LC', + dialCode: '+1758', + flag: '🇱🇨', + flagImage: 'assets/images/flags/lc.png', + nativeName: 'Saint Lucia', + placeholder: '7582841234', + }, + { + name: 'Saint Martin (France)', + code: 'MF', + dialCode: '+590', + flag: '🇲🇫', + flagImage: 'assets/images/flags/mf.png', + nativeName: 'Saint-Martin', + placeholder: '0690001234', + }, + { + name: 'Saint Pierre and Miquelon', + code: 'PM', + dialCode: '+508', + flag: '🇫🇷', + flagImage: 'assets/images/flags/fr.png', + nativeName: 'Saint-Pierre-et-Miquelon', + placeholder: '0508123456', + }, + { + name: 'Saint Vincent and the Grenadines', + code: 'VC', + dialCode: '+1784', + flag: '🇻🇨', + flagImage: 'assets/images/flags/vc.png', + nativeName: 'Saint Vincent and the Grenadines', + placeholder: '7844301234', + }, + { + name: 'Samoa', + code: 'WS', + dialCode: '+685', + flag: '🇼🇸', + flagImage: 'assets/images/flags/ws.png', + nativeName: 'Samoa', + placeholder: '7212345', + }, + { + name: 'San Marino', + code: 'SM', + dialCode: '+378', + flag: '🇸🇲', + flagImage: 'assets/images/flags/sm.png', + nativeName: 'San Marino', + placeholder: '66661234', + }, + { + name: 'São Tomé and Príncipe', + code: 'ST', + dialCode: '+239', + flag: '🇸🇹', + flagImage: 'assets/images/flags/st.png', + nativeName: 'São Tomé e Príncipe', + placeholder: '9812345', + }, + { + name: 'Saudi Arabia', + code: 'SA', + dialCode: '+966', + flag: '🇸🇦', + flagImage: 'assets/images/flags/sa.png', + nativeName: 'المملكة العربية السعودية', + placeholder: '501234567', + }, + { + name: 'Senegal', + code: 'SN', + dialCode: '+221', + flag: '🇸🇳', + flagImage: 'assets/images/flags/sn.png', + nativeName: 'Sénégal', + placeholder: '701234567', + }, + { + name: 'Serbia', + code: 'RS', + dialCode: '+381', + flag: '🇷🇸', + flagImage: 'assets/images/flags/rs.png', + nativeName: 'Србија', + placeholder: '0601234567', + }, + { + name: 'Seychelles', + code: 'SC', + dialCode: '+248', + flag: '🇸🇨', + flagImage: 'assets/images/flags/sc.png', + nativeName: 'Seychelles', + placeholder: '2512345', + }, + { + name: 'Sierra Leone', + code: 'SL', + dialCode: '+232', + flag: '🇸🇱', + flagImage: 'assets/images/flags/sl.png', + nativeName: 'Sierra Leone', + placeholder: '076123456', + }, + { + name: 'Singapore', + code: 'SG', + dialCode: '+65', + flag: '🇸🇬', + flagImage: 'assets/images/flags/sg.png', + nativeName: 'Singapore', + placeholder: '81234567', + }, + { + name: 'Sint Maarten', + code: 'SX', + dialCode: '+1721', + flag: '🇸🇽', + flagImage: 'assets/images/flags/sx.png', + nativeName: 'Sint Maarten', + placeholder: '7215201234', + }, + { + name: 'Slovakia', + code: 'SK', + dialCode: '+421', + flag: '🇸🇰', + flagImage: 'assets/images/flags/sk.png', + nativeName: 'Slovensko', + placeholder: '0912123456', + }, + { + name: 'Slovenia', + code: 'SI', + dialCode: '+386', + flag: '🇸🇮', + flagImage: 'assets/images/flags/si.png', + nativeName: 'Slovenija', + placeholder: '031234567', + }, + { + name: 'Solomon Islands', + code: 'SB', + dialCode: '+677', + flag: '🇸🇧', + flagImage: 'assets/images/flags/sb.png', + nativeName: 'Solomon Islands', + placeholder: '7412345', + }, + { + name: 'Somalia', + code: 'SO', + dialCode: '+252', + flag: '🇸🇴', + flagImage: 'assets/images/flags/so.png', + nativeName: 'Soomaaliya', + placeholder: '0612345678', + }, + { + name: 'South Africa', + code: 'ZA', + dialCode: '+27', + flag: '🇿🇦', + flagImage: 'assets/images/flags/za.png', + nativeName: 'South Africa', + placeholder: '0712345678', + }, + { + name: 'South Korea', + code: 'KR', + dialCode: '+82', + flag: '🇰🇷', + flagImage: 'assets/images/flags/kr.png', + nativeName: '대한민국', + placeholder: '01012345678', + }, + { + name: 'South Sudan', + code: 'SS', + dialCode: '+211', + flag: '🇸🇸', + flagImage: 'assets/images/flags/ss.png', + nativeName: 'جنوب السودان', + placeholder: '0977123456', + }, + { + name: 'Spain', + code: 'ES', + dialCode: '+34', + flag: '🇪🇸', + flagImage: 'assets/images/flags/es.png', + nativeName: 'España', + placeholder: '612345678', + }, + { + name: 'Sri Lanka', + code: 'LK', + dialCode: '+94', + flag: '🇱🇰', + flagImage: 'assets/images/flags/lk.png', + nativeName: 'ශ්‍රී ලංකාව', + placeholder: '0712345678', + }, + { + name: 'Sudan', + code: 'SD', + dialCode: '+249', + flag: '🇸🇩', + flagImage: 'assets/images/flags/sd.png', + nativeName: 'السودان', + placeholder: '0912345678', + }, + { + name: 'Suriname', + code: 'SR', + dialCode: '+597', + flag: '🇸🇷', + flagImage: 'assets/images/flags/sr.png', + nativeName: 'Suriname', + placeholder: '7412345', + }, + { + name: 'Svalbard and Jan Mayen', + code: 'SJ', + dialCode: '+47', + flag: '🇸🇯', + flagImage: 'assets/images/flags/sj.png', + nativeName: 'Svalbard og Jan Mayen', + placeholder: '79912345', + }, + { + name: 'Sweden', + code: 'SE', + dialCode: '+46', + flag: '🇸🇪', + flagImage: 'assets/images/flags/se.png', + nativeName: 'Sverige', + placeholder: '0701234567', + }, + { + name: 'Switzerland', + code: 'CH', + dialCode: '+41', + flag: '🇨🇭', + flagImage: 'assets/images/flags/ch.png', + nativeName: 'Schweiz', + placeholder: '0791234567', + }, + { + name: 'Syria', + code: 'SY', + dialCode: '+963', + flag: '🇸🇾', + flagImage: 'assets/images/flags/sy.png', + nativeName: 'سوريا', + placeholder: '0944567890', + }, + // T + { + name: 'Taiwan', + code: 'TW', + dialCode: '+886', + flag: '🇹🇼', + flagImage: 'assets/images/flags/tw.png', + nativeName: '台灣', + placeholder: '0912345678', + }, + { + name: 'Tajikistan', + code: 'TJ', + dialCode: '+992', + flag: '🇹🇯', + flagImage: 'assets/images/flags/tj.png', + nativeName: 'Tajikistan', + placeholder: '917123456', + }, + { + name: 'Tanzania', + code: 'TZ', + dialCode: '+255', + flag: '🇹🇿', + flagImage: 'assets/images/flags/tz.png', + nativeName: 'Tanzania', + placeholder: '0712345678', + }, + { + name: 'Thailand', + code: 'TH', + dialCode: '+66', + flag: '🇹🇭', + flagImage: 'assets/images/flags/th.png', + nativeName: 'ไทย', + placeholder: '0812345678', + }, + { + name: 'Timor-Leste', + code: 'TL', + dialCode: '+670', + flag: '🇹🇱', + flagImage: 'assets/images/flags/tl.png', + nativeName: 'Timor-Leste', + placeholder: '77212345', + }, + { + name: 'Togo', + code: 'TG', + dialCode: '+228', + flag: '🇹🇬', + flagImage: 'assets/images/flags/tg.png', + nativeName: 'Togo', + placeholder: '90112345', + }, + { + name: 'Tokelau', + code: 'TK', + dialCode: '+690', + flag: '🇹🇰', + flagImage: 'assets/images/flags/tk.png', + nativeName: 'Tokelau', + }, + { + name: 'Tonga', + code: 'TO', + dialCode: '+676', + flag: '🇹🇴', + flagImage: 'assets/images/flags/to.png', + nativeName: 'Tonga', + placeholder: '7715123', + }, + { + name: 'Trinidad and Tobago', + code: 'TT', + dialCode: '+1868', + flag: '🇹🇹', + flagImage: 'assets/images/flags/tt.png', + nativeName: 'Trinidad and Tobago', + placeholder: '8682911234', + }, + { + name: 'Tunisia', + code: 'TN', + dialCode: '+216', + flag: '🇹🇳', + flagImage: 'assets/images/flags/tn.png', + nativeName: 'تونس', + placeholder: '20123456', + }, + { + name: 'Turkey', + code: 'TR', + dialCode: '+90', + flag: '🇹🇷', + flagImage: 'assets/images/flags/tr.png', + nativeName: 'Türkiye', + placeholder: '5321234567', + }, + { + name: 'Turkmenistan', + code: 'TM', + dialCode: '+993', + flag: '🇹🇲', + flagImage: 'assets/images/flags/tm.png', + nativeName: 'Turkmenistan', + placeholder: '65123456', + }, + { + name: 'Turks and Caicos Islands', + code: 'TC', + dialCode: '+1649', + flag: '🇹🇨', + flagImage: 'assets/images/flags/tc.png', + nativeName: 'Turks and Caicos Islands', + placeholder: '6493311234', + }, + { + name: 'Tuvalu', + code: 'TV', + dialCode: '+688', + flag: '🇹🇻', + flagImage: 'assets/images/flags/tv.png', + nativeName: 'Tuvalu', + placeholder: '901234', + }, + // U + { + name: 'Uganda', + code: 'UG', + dialCode: '+256', + flag: '🇺🇬', + flagImage: 'assets/images/flags/ug.png', + nativeName: 'Uganda', + placeholder: '0712345678', + }, + { + name: 'Ukraine', + code: 'UA', + dialCode: '+380', + flag: '🇺🇦', + flagImage: 'assets/images/flags/ua.png', + nativeName: 'Україна', + placeholder: '0671234567', + }, + { + name: 'United Arab Emirates', + code: 'AE', + dialCode: '+971', + flag: '🇦🇪', + flagImage: 'assets/images/flags/ae.png', + nativeName: 'الإمارات العربية المتحدة', + placeholder: '0501234567', + }, + // { // Move this in top + // name: 'United Kingdom' + // code: 'GB' + // dialCode: '+44' + // flag: '🇬🇧' + // flagImage: 'assets/images/flags/gb.png' + // nativeName: '+44', + // + // + // + // + // }, + // { // Move this in top + // name: 'United States' + // code: 'US' + // dialCode: '+1' + // flag: '🇺🇸' + // flagImage: 'assets/images/flags/us.png' + // nativeName: '+1', + // + // + // + // + // }, + { + name: 'Uruguay', + code: 'UY', + dialCode: '+598', + flag: '🇺🇾', + flagImage: 'assets/images/flags/uy.png', + nativeName: 'Uruguay', + placeholder: '094231234', + }, + { + name: 'US Virgin Islands', + code: 'VI', + dialCode: '+1340', + flag: '🇻🇮', + flagImage: 'assets/images/flags/vi.png', + nativeName: 'U.S. Virgin Islands', + placeholder: '3403411234', + }, + { + name: 'Uzbekistan', + code: 'UZ', + dialCode: '+998', + flag: '🇺🇿', + flagImage: 'assets/images/flags/uz.png', + nativeName: 'Oʻzbekiston', + placeholder: '901234567', + }, + // V + { + name: 'Vanuatu', + code: 'VU', + dialCode: '+678', + flag: '🇻🇺', + flagImage: 'assets/images/flags/vu.png', + nativeName: 'Vanuatu', + placeholder: '5912345', + }, + { + name: 'Vatican City', + code: 'VA', + dialCode: '+379', // Old +39 + flag: '🇻🇦', + flagImage: 'assets/images/flags/va.png', + nativeName: 'Città del Vaticano', + placeholder: '3451234', + }, + { + name: 'Venezuela', + code: 'VE', + dialCode: '+58', + flag: '🇻🇪', + flagImage: 'assets/images/flags/ve.png', + nativeName: 'Venezuela', + placeholder: '4121234567', + }, + { + name: 'Vietnam', + code: 'VN', + dialCode: '+84', + flag: '🇻🇳', + flagImage: 'assets/images/flags/vn.png', + nativeName: 'Việt Nam', + placeholder: '0912345678', + }, + // W + { + name: 'Wallis and Futuna', + code: 'WF', + dialCode: '+681', + flag: '🇫🇷', + flagImage: 'assets/images/flags/fr.png', + nativeName: 'Wallis-et-Futuna', + placeholder: '501234', + }, + { + name: 'Western Sahara', + code: 'EH', + dialCode: '+212', + flag: '🇪🇭', + flagImage: 'assets/images/flags/eh.png', + nativeName: 'الصحراء الغربية', + placeholder: '0612345678', + }, + // Y + { + name: 'Yemen', + code: 'YE', + dialCode: '+967', + flag: '🇾🇪', + flagImage: 'assets/images/flags/ye.png', + nativeName: 'اليمن', + placeholder: '0712345678', + }, + // Z + { + name: 'Zambia', + code: 'ZM', + dialCode: '+260', + flag: '🇿🇲', + flagImage: 'assets/images/flags/zm.png', + nativeName: 'Zambia', + placeholder: '0971234567', + }, + { + name: 'Zimbabwe', + code: 'ZW', + dialCode: '+263', + flag: '🇿🇼', + flagImage: 'assets/images/flags/zw.png', + nativeName: 'Zimbabwe', + placeholder: '0712345678', + }, +]; diff --git a/libs/custom-validator/src/index.ts b/libs/custom-validator/src/index.ts index bd8d81a0..52abec83 100644 --- a/libs/custom-validator/src/index.ts +++ b/libs/custom-validator/src/index.ts @@ -495,4 +495,27 @@ export class CustomValidators { return null; }; } + + public static passwordStrength(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const value: string = control.value ?? ''; + const errors: ValidationErrors = {}; + if (value.length < 8) { + errors['minLength'] = true; + } + if (!/[A-Z]/.test(value)) { + errors['uppercase'] = true; + } + if (!/[a-z]/.test(value)) { + errors['lowercase'] = true; + } + if (!/[0-9]/.test(value)) { + errors['number'] = true; + } + if (!/[^A-Za-z0-9]/.test(value)) { + errors['symbol'] = true; + } + return Object.keys(errors).length ? errors : null; + }; + } } diff --git a/libs/services/interceptor/error-interceptor/src/lib/services-interceptor-error-interceptor.module.ts b/libs/services/interceptor/error-interceptor/src/lib/services-interceptor-error-interceptor.module.ts index ec287a49..dde7a26b 100644 --- a/libs/services/interceptor/error-interceptor/src/lib/services-interceptor-error-interceptor.module.ts +++ b/libs/services/interceptor/error-interceptor/src/lib/services-interceptor-error-interceptor.module.ts @@ -21,6 +21,8 @@ export class ErrorInterceptor implements HttpInterceptor { if ( request.url.includes('api/register') || request.url.includes('api/googleLogin') || + request.url.includes('api/login') || + request.url.includes('api/onboarding') || request.url.includes('flow.sokt.io') || this.cookieService.get('authToken') ) { diff --git a/libs/services/proxy/users/src/lib/services-proxy-users.module.ts b/libs/services/proxy/users/src/lib/services-proxy-users.module.ts index 1d31eb71..0647345f 100644 --- a/libs/services/proxy/users/src/lib/services-proxy-users.module.ts +++ b/libs/services/proxy/users/src/lib/services-proxy-users.module.ts @@ -94,4 +94,16 @@ export class UsersService { public register(formData: any): Observable { return this.httpNoAuth.post(UsersUrl.register(this.baseURL), formData, this.options); } + + public emailLogin(email: string, password: string): Observable { + return this.httpNoAuth.post(UsersUrl.emailLogin(this.baseURL), { email, password }, this.options); + } + + public submitOnboarding(payload: { + user: { name: string; mobile: string }; + client: { name: string; mobile: string }; + onboarding_token?: string; + }): Observable { + return this.httpNoAuth.post(UsersUrl.onboarding(this.baseURL), payload, this.options); + } } diff --git a/libs/urls/users-urls/src/index.ts b/libs/urls/users-urls/src/index.ts index 869772af..aa38052a 100644 --- a/libs/urls/users-urls/src/index.ts +++ b/libs/urls/users-urls/src/index.ts @@ -3,6 +3,8 @@ import { createUrl } from '@proxy/service'; export const UsersUrl = { getUsers: (baseUrl) => createUrl(baseUrl, 'clientUsers'), register: (baseUrl) => createUrl(baseUrl, 'register'), + emailLogin: (baseUrl) => createUrl(baseUrl, 'login'), + onboarding: (baseUrl) => createUrl(baseUrl, 'onboarding'), getRoles: (baseUrl) => createUrl(baseUrl, ':referenceId/cRoles'), createRole: (baseUrl) => createUrl(baseUrl, ':referenceId/cRoles'), updateRole: (baseUrl) => createUrl(baseUrl, ':referenceId/cRoles/:id'),