Refactor Passport Application flow by splitting each step into separate components and finalize Step 3 logic

This commit is contained in:
Mochammad Adhi Buchori
2025-04-24 23:48:39 +07:00
parent 2c0ea70fb3
commit 89f93aa46b
18 changed files with 1208 additions and 710 deletions

View File

@ -17,12 +17,10 @@ import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {Button, PaperProvider} from 'react-native-paper';
import StepIndicator from '../../components/StepIndicator';
import TextInputComponent from '../../components/TextInput';
import genderData from '../../data/DropdownData/GenderData';
import DialogApplicationPassport from '../../components/dialog/DialogApplicationPassport';
import DialogDontHaveYetPassport from '../../components/dialog/DialogDontHaveYetPassport';
import DialogPassportInfo from '../../components/dialog/DialogPassportInfo';
import DialogLostOrDamagedPassport from '../../components/dialog/DialogLostOrDamagedPassport';
import destinationCountryData from '../../data/DropdownData/DestinationCountryData';
import familyRelationshipData from '../../data/DropdownData/FamilyRelationshipData';
import FontFamily from '../../../assets/styles/FontFamily';
import passportAppointmentData from '../../data/History/PassportAppointmentData';
@ -32,19 +30,28 @@ import Step5Verification from './steps/Step5Verification/Step5Verification';
import Step3Payment from './steps/Step3Payment/Step3Payment';
// Data
import civilStatusData from '../../data/DropdownData/CivilStatusData';
import arrivalDateGuidelinesData from '../../data/Steps/ArrivalDateGuidelinesData';
// Options Data
import passportForOptions from '../../data/Options/PassportForOptions';
import hasHadPassportBeforeOptions from '../../data/Options/HasHadPassportBeforeOptions';
import previousPassportConditionOptions from '../../data/Options/PreviousPassportConditionOptions';
import passportApplicationPurposeOptions from '../../data/Options/PassportApplicationPurposeOptions';
import destinationCountryOptions from '../../data/Options/destinationCountryOptions';
import durationAbroadOptions from '../../data/Options/DurationAbroadOptions';
import destinationFamilyContactOptions from '../../data/Options/DestinationFamilyContactOptions';
import Step4DataConfirmationSubStep2 from './steps/Step4DataConfirmation/Step4DataConfirmationSubStep2';
import Step4DataConfirmationSubStep1 from './steps/Step4DataConfirmation/Step4DataConfirmationSubStep1';
import Step1PersonalInfoSubStep1 from './steps/Step1PersonalInfo/Step1PersonalInfoSubStep1';
import Step1PersonalInfoSubStep2 from './steps/Step1PersonalInfo/Step1PersonalInfoSubStep2';
import Step1PersonalInfoSubStep3 from './steps/Step1PersonalInfo/Step1PersonalInfoSubStep3';
import Step2SupportingDocsSubStep1 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep1';
import Step2SupportingDocsSubStep2 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep2';
import Step2SupportingDocsSubStep3 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep3';
import Step2SupportingDocsSubStep4 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep4';
import Step2SupportingDocsSubStep5 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep5';
import Step2SupportingDocsSubStep6 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep6';
import Step2SupportingDocsSubStep7 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep7';
import Step2SupportingDocsSubStep8 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep8';
import Step2SupportingDocsSubStep9 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep9';
import Step2SupportingDocsSubStep10 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep10';
import Step2SupportingDocsSubStep11 from './steps/Step2SupportingDocs/Step2SupportingDocsSubStep11';
type RegularPassportScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
@ -58,6 +65,8 @@ type RenderApplicationStepsContentProps = {
setSubStep: (subStep: number) => void;
selectedOption: string;
setSelectedOption: (val: string) => void;
selectedPassportOption: string;
setSelectedPassportOption: (val: string) => void;
checkedOption: boolean;
setCheckedOption: React.Dispatch<React.SetStateAction<boolean>>;
showDontHaveYetDialog: () => void;
@ -75,6 +84,8 @@ const RenderApplicationStepsContent = (
setSubStep,
selectedOption,
setSelectedOption,
selectedPassportOption,
setSelectedPassportOption,
checkedOption,
setCheckedOption,
showDontHaveYetDialog,
@ -85,148 +96,15 @@ const RenderApplicationStepsContent = (
if (step === 1) {
switch (subStep) {
case 1:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto KTP Anda
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat
jelas, dan jangan gunakan foto dari Live Mode sebelum
melanjutkan.
</Text>
</View>
<View style={styles.documentImage}>
<Text style={styles.documentImageSupportText}>Foto KTP</Text>
<View
style={[
styles.documentImageCropped,
{backgroundColor: Colors.neutral100.color},
]}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(2)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Ambil Foto
</Button>
<Button
mode="outlined"
onPress={() => {}}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Upload Galeri
</Button>
</View>
</View>
</ScrollView>
);
return <Step1PersonalInfoSubStep1 setSubStep={setSubStep} />;
case 2:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto KTP Anda
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat
jelas, dan jangan gunakan foto dari Live Mode sebelum
melanjutkan.
</Text>
</View>
<View style={styles.documentImage} />
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(3)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Pilih Foto
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(1)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Ulangi
</Button>
</View>
</View>
</ScrollView>
);
return <Step1PersonalInfoSubStep2 setSubStep={setSubStep} />;
case 3:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.documentImageContainer}>
<View style={styles.documentImageCropped} />
</View>
<View
style={[styles.subStepTextInputContainer, {marginBottom: 24}]}>
<TextInputComponent
title="Nama Lengkap Pemohon"
placeholder="Nama Lengkap Anda"
isRequired
/>
<TextInputComponent
title="NIK"
placeholder="Nama NIK Anda"
isRequired
/>
<View style={styles.subStepTextInputRowContainer}>
<View style={styles.subStepTextInputFlex}>
<TextInputComponent
title="Tanggal Lahir"
placeholder="DD/MM/YYYY"
isRequired
isDate
/>
</View>
<View style={styles.subStepTextInputFlex}>
<TextInputComponent
title="Jenis Kelamin"
placeholder="Jenis Kelamin"
isRequired
isDropdown
dropdownItemData={genderData}
/>
</View>
</View>
<TextInputComponent
title="Status Sipil"
placeholder="Pilih Status Sipil Anda"
isRequired
isDropdown
dropdownItemData={civilStatusData}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => {
setStep(2);
setSubStep(1);
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(2)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Kembali
</Button>
</View>
</View>
</ScrollView>
<Step1PersonalInfoSubStep3
setStep={setStep}
setSubStep={setSubStep}
/>
);
default:
return null;
@ -237,560 +115,66 @@ const RenderApplicationStepsContent = (
switch (subStep) {
case 1:
return (
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setStep(1);
setSubStep(3);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Apakah Anda sudah pernah memiliki paspor?
</Text>
{hasHadPassportBeforeOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => {
setSelectedOption(value);
value === 'already'
? setSubStep(2)
: showDontHaveYetDialog();
}}
/>
))}
</View>
</View>
<Step2SupportingDocsSubStep1
setStep={setStep}
setSubStep={setSubStep}
selectedPassportOption={selectedPassportOption}
setSelectedPassportOption={setSelectedPassportOption}
showDontHaveYetDialog={showDontHaveYetDialog}
/>
);
case 2:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(1);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Bagaimana kondisi paspor lama Anda?
</Text>
<Pressable
onPress={() => showPassportInfoDialog()}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon
name="alert-circle-outline"
size={18}
color={Colors.secondary30.color}
/>
<Text
style={[
styles.subStepButtonBackText,
{color: Colors.secondary30.color},
]}>
Klik di sini untuk melihat informasi kondisi paspor
</Text>
</Pressable>
{previousPassportConditionOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => {
setSelectedOption(value);
}}
/>
))}
</View>
<Button
mode="contained"
onPress={() => {
(selectedOption === 'expired' ||
selectedOption === 'full_pages') &&
setSubStep(3);
(selectedOption === 'lost' ||
selectedOption === 'damaged' ||
selectedOption === 'lost_due_to_force_majeure' ||
selectedOption === 'damaged_due_to_force_majeure') &&
showLostOrDamagedPassportDialog();
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
<Step2SupportingDocsSubStep2
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
showPassportInfoDialog={showPassportInfoDialog}
showLostOrDamagedPassportDialog={showLostOrDamagedPassportDialog}
/>
);
case 3:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(2);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto Paspor Lama Anda (Halaman 2 Paspor)
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat
jelas, dan jangan gunakan foto dari Live Mode sebelum
melanjutkan.
</Text>
</View>
<View style={styles.documentImage}>
<Text style={styles.documentImageSupportText}>
Foto Halaman 2 Paspor Lama
</Text>
<View
style={[
styles.documentImageCropped,
{backgroundColor: Colors.neutral100.color},
]}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(4)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Ambil Foto
</Button>
<Button
mode="outlined"
onPress={() => {}}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Upload Galeri
</Button>
</View>
</View>
</ScrollView>
);
return <Step2SupportingDocsSubStep3 setSubStep={setSubStep} />;
case 4:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(3);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto Paspor Lama Anda (Halaman 2 Paspor)
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat
jelas, dan jangan gunakan foto dari Live Mode sebelum
melanjutkan.
</Text>
</View>
<View style={styles.documentImage} />
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(5)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Pilih Foto
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(3)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Ulangi
</Button>
</View>
</View>
</ScrollView>
);
return <Step2SupportingDocsSubStep4 setSubStep={setSubStep} />;
case 5:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(4);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Nomor paspor lama Anda"
placeholder="Masukkan nomor paspor lama Anda"
/>
<View>
<View style={styles.textInputBulletTextWrapper}>
<Text style={styles.textInputSupportText}></Text>
<Text style={styles.textInputSupportText}>
Nomor paspor lama minimal 7 karakter
</Text>
</View>
<View style={styles.textInputBulletTextWrapper}>
<Text style={styles.textInputSupportText}></Text>
<Text style={styles.textInputSupportText}>
Tulis nomor paspor tanpa menggunakan spasi. Contoh:
B12345678
</Text>
</View>
</View>
</View>
<Button
mode="contained"
onPress={() => setSubStep(6)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
return <Step2SupportingDocsSubStep5 setSubStep={setSubStep} />;
case 6:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(5);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Apakah tujuan Anda membuat paspor?
</Text>
{passportApplicationPurposeOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => {
setSelectedOption(value);
}}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(7)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
<Step2SupportingDocsSubStep6
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
/>
);
case 7:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(6);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Negara mana yang akan Anda tuju?"
placeholder="Masukkan negara tujuan"
isDropdown
dropdownItemData={destinationCountryData}
/>
{destinationCountryOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => {
setSelectedOption(value);
}}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(8)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
<Step2SupportingDocsSubStep7
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
/>
);
case 8:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(7);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Di mana tempat tinggal Anda di negara tujuan?"
placeholder="Masukkan alamat"
supportText="0/100 karakter"
containerHeight={90}
isMultiline
/>
</View>
<Button
mode="contained"
onPress={() => setSubStep(9)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
return <Step2SupportingDocsSubStep8 setSubStep={setSubStep} />;
case 9:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(8);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Berapa lama Anda berencana berada di luar negeri?
</Text>
{durationAbroadOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => setSelectedOption(value)}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(10)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
<Step2SupportingDocsSubStep9
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
/>
);
case 10:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(9);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Nomor telepon keluarga/kerabat terdekat Anda di Indonesia yang
dapat dihubungi
</Text>
<TextInputComponent
title="Nama Kerabat"
placeholder="Masukkan Nama Kerabat Anda"
isRequired
/>
<TextInputComponent
title="Nomor Telepon"
placeholder="Contoh: 08513456789"
isRequired
/>
<TextInputComponent
title="Keterangan Hubungan Keluarga"
placeholder="Pilih Hubungan"
isRequired
isDropdown
dropdownItemData={familyRelationshipData}
/>
</View>
<Button
mode="contained"
onPress={() => setSubStep(11)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
return <Step2SupportingDocsSubStep10 setSubStep={setSubStep} />;
case 11:
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(10);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<View style={{gap: 4}}>
<Text style={styles.questionnaireData}>
Nomor telepon keluarga/kerabat di negara tujuan
</Text>
<Text
style={[
styles.questionnaireData,
{...FontFamily.notoSansRegular},
]}>
(Opsional)
</Text>
</View>
<TextInputComponent
title="Nama Kerabat"
placeholder="Masukkan Nama Kerabat Anda"
/>
<TextInputComponent
title="Nomor Telepon"
placeholder="Contoh: 08513456789"
/>
<TextInputComponent
title="Keterangan Hubungan Keluarga"
placeholder="Pilih Hubungan"
isDropdown
dropdownItemData={familyRelationshipData}
/>
{destinationFamilyContactOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => {
setSelectedOption(value);
}}
/>
))}
</View>
<Button
mode="contained"
onPress={() => {
setStep(3), setSubStep(1);
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
<Step2SupportingDocsSubStep11
setStep={setStep}
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
/>
);
default:
return null;
@ -819,7 +203,13 @@ const RenderApplicationStepsContent = (
}
switch (step) {
case 3:
return <Step3Payment setStep={setStep} setSubStep={setSubStep} />;
return (
<Step3Payment
setStep={setStep}
setSubStep={setSubStep}
selectedPassportOption={selectedPassportOption}
/>
);
case 5:
return (
<Step5Verification
@ -892,6 +282,7 @@ function RegularPassportScreen() {
// State management
const [selectedOption, setSelectedOption] = useState('');
const [selectedPassportOption, setSelectedPassportOption] = useState('');
const [checkedOption, setCheckedOption] = useState(false);
const [showApplicationStepsContent, setShowApplicationStepsContent] =
useState(false);
@ -970,6 +361,8 @@ function RegularPassportScreen() {
setSubStep={setSubStep}
selectedOption={selectedOption}
setSelectedOption={setSelectedOption}
selectedPassportOption={selectedPassportOption}
setSelectedPassportOption={setSelectedPassportOption}
checkedOption={checkedOption}
setCheckedOption={setCheckedOption}
showDontHaveYetDialog={showDontHaveYetDialog}

View File

@ -0,0 +1,54 @@
import React from 'react';
import {ScrollView, View, Text} from 'react-native';
import {Button} from 'react-native-paper';
import styles from '../styles';
import Colors from '../../../../../assets/styles/Colors';
type Step1PersonalInfoSubStep1Props = {
setSubStep: (val: number) => void;
};
const Step1PersonalInfoSubStep1 = ({
setSubStep,
}: Step1PersonalInfoSubStep1Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>Ambil/Upload Foto KTP Anda</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat jelas,
dan jangan gunakan foto dari Live Mode sebelum melanjutkan.
</Text>
</View>
<View style={styles.documentImage}>
<Text style={styles.documentImageSupportText}>Foto KTP</Text>
<View
style={[
styles.documentImageCropped,
{backgroundColor: Colors.neutral100.color},
]}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(2)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Ambil Foto
</Button>
<Button
mode="outlined"
onPress={() => {}}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Upload Galeri
</Button>
</View>
</View>
</ScrollView>
);
};
export default Step1PersonalInfoSubStep1;

View File

@ -0,0 +1,48 @@
import React from 'react';
import {ScrollView, View, Text} from 'react-native';
import {Button} from 'react-native-paper';
import styles from '../styles';
import Colors from '../../../../../assets/styles/Colors';
type Step1PersonalInfoSubStep2Props = {
setSubStep: (val: number) => void;
};
const Step1PersonalInfoSubStep2 = ({
setSubStep,
}: Step1PersonalInfoSubStep2Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>Ambil/Upload Foto KTP Anda</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat jelas,
dan jangan gunakan foto dari Live Mode sebelum melanjutkan.
</Text>
</View>
<View style={styles.documentImage} />
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(3)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Pilih Foto
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(1)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Ulangi
</Button>
</View>
</View>
</ScrollView>
);
};
export default Step1PersonalInfoSubStep2;

View File

@ -0,0 +1,89 @@
import React from 'react';
import {ScrollView, View} from 'react-native';
import {Button} from 'react-native-paper';
import styles from '../styles';
import TextInputComponent from '../../../../components/TextInput';
import genderData from '../../../../data/DropdownData/GenderData';
import civilStatusData from '../../../../data/DropdownData/CivilStatusData';
import Colors from '../../../../../assets/styles/Colors';
type Step1PersonalInfoSubStep3Props = {
setStep: (val: number) => void;
setSubStep: (val: number) => void;
};
const Step1PersonalInfoSubStep3 = ({
setStep,
setSubStep,
}: Step1PersonalInfoSubStep3Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<View style={styles.documentImageContainer}>
<View style={styles.documentImageCropped} />
</View>
<View style={[styles.subStepTextInputContainer, {marginBottom: 24}]}>
<TextInputComponent
title="Nama Lengkap Pemohon"
placeholder="Nama Lengkap Anda"
isRequired
/>
<TextInputComponent
title="NIK"
placeholder="Nama NIK Anda"
isRequired
/>
<View style={styles.subStepTextInputRowContainer}>
<View style={styles.subStepTextInputFlex}>
<TextInputComponent
title="Tanggal Lahir"
placeholder="DD/MM/YYYY"
isRequired
isDate
/>
</View>
<View style={styles.subStepTextInputFlex}>
<TextInputComponent
title="Jenis Kelamin"
placeholder="Jenis Kelamin"
isRequired
isDropdown
dropdownItemData={genderData}
/>
</View>
</View>
<TextInputComponent
title="Status Sipil"
placeholder="Pilih Status Sipil Anda"
isRequired
isDropdown
dropdownItemData={civilStatusData}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => {
setStep(2);
setSubStep(1);
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(2)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Kembali
</Button>
</View>
</View>
</ScrollView>
);
};
export default Step1PersonalInfoSubStep3;

View File

@ -0,0 +1,62 @@
import React from 'react';
import {View, Pressable, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import styles from '../styles';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import hasHadPassportBeforeOptions from '../../../../data/Options/HasHadPassportBeforeOptions';
type Step2SupportingDocsSubStep1Props = {
setStep: (step: number) => void;
setSubStep: (subStep: number) => void;
selectedPassportOption: string;
setSelectedPassportOption: (value: string) => void;
showDontHaveYetDialog: () => void;
};
const Step2SupportingDocsSubStep1 = ({
setStep,
setSubStep,
selectedPassportOption,
setSelectedPassportOption,
showDontHaveYetDialog,
}: Step2SupportingDocsSubStep1Props) => {
return (
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setStep(1);
setSubStep(3);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Apakah Anda sudah pernah memiliki paspor?
</Text>
{hasHadPassportBeforeOptions.map(option => (
<RadioButtonOptionComponent
key={option.value}
label={option.label}
description={option.description}
value={option.value}
selectedValue={selectedPassportOption}
onSelect={value => {
setSelectedPassportOption(value);
value === 'already' ? setSubStep(2) : showDontHaveYetDialog();
}}
/>
))}
</View>
</View>
);
};
export default Step2SupportingDocsSubStep1;

View File

@ -0,0 +1,72 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import TextInputComponent from '../../../../components/TextInput';
import Colors from '../../../../../assets/styles/Colors';
import familyRelationshipData from '../../../../data/DropdownData/FamilyRelationshipData';
type Step2SupportingDocsSubStep10Props = {
setSubStep: (step: number) => void;
};
const Step2SupportingDocsSubStep10 = ({
setSubStep,
}: Step2SupportingDocsSubStep10Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(9)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Nomor telepon keluarga/kerabat terdekat Anda di Indonesia yang dapat
dihubungi
</Text>
<TextInputComponent
title="Nama Kerabat"
placeholder="Masukkan Nama Kerabat Anda"
isRequired
/>
<TextInputComponent
title="Nomor Telepon"
placeholder="Contoh: 08513456789"
isRequired
/>
<TextInputComponent
title="Keterangan Hubungan Keluarga"
placeholder="Pilih Hubungan"
isRequired
isDropdown
dropdownItemData={familyRelationshipData}
/>
</View>
<Button
mode="contained"
onPress={() => setSubStep(11)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep10;

View File

@ -0,0 +1,100 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import FontFamily from '../../../../../assets/styles/FontFamily';
import TextInputComponent from '../../../../components/TextInput';
import destinationFamilyContactOptions from '../../../../data/Options/DestinationFamilyContactOptions';
import familyRelationshipData from '../../../../data/DropdownData/FamilyRelationshipData';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep11Props = {
setStep: (step: number) => void;
setSubStep: (subStep: number) => void;
selectedOption: string;
setSelectedOption: (value: string) => void;
};
const Step2SupportingDocsSubStep11 = ({
setStep,
setSubStep,
selectedOption,
setSelectedOption,
}: Step2SupportingDocsSubStep11Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(10)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<View style={{gap: 4}}>
<Text style={styles.questionnaireData}>
Nomor telepon keluarga/kerabat di negara tujuan
</Text>
<Text
style={[
styles.questionnaireData,
{...FontFamily.notoSansRegular},
]}>
(Opsional)
</Text>
</View>
<TextInputComponent
title="Nama Kerabat"
placeholder="Masukkan Nama Kerabat Anda"
/>
<TextInputComponent
title="Nomor Telepon"
placeholder="Contoh: 08513456789"
/>
<TextInputComponent
title="Keterangan Hubungan Keluarga"
placeholder="Pilih Hubungan"
isDropdown
dropdownItemData={familyRelationshipData}
/>
{destinationFamilyContactOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => setSelectedOption(value)}
/>
))}
</View>
<Button
mode="contained"
onPress={() => {
setStep(3);
setSubStep(1);
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep11;

View File

@ -0,0 +1,97 @@
import React from 'react';
import {ScrollView, View, Pressable, Text} from 'react-native';
import {Button} from 'react-native-paper';
import previousPassportConditionOptions from '../../../../data/Options/PreviousPassportConditionOptions';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import Colors from '../../../../../assets/styles/Colors';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import styles from '../styles';
type Step2SupportingDocsSubStep2Props = {
setSubStep: (step: number) => void;
selectedOption: string;
setSelectedOption: (value: string) => void;
showPassportInfoDialog: () => void;
showLostOrDamagedPassportDialog: () => void;
};
const Step2SupportingDocsSubStep2 = ({
setSubStep,
selectedOption,
setSelectedOption,
showPassportInfoDialog,
showLostOrDamagedPassportDialog,
}: Step2SupportingDocsSubStep2Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(1);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{transform: [{scale: pressed ? 0.99 : 1}]},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Bagaimana kondisi paspor lama Anda?
</Text>
<Pressable
onPress={showPassportInfoDialog}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{transform: [{scale: pressed ? 0.99 : 1}]},
]}>
<Icon
name="alert-circle-outline"
size={18}
color={Colors.secondary30.color}
/>
<Text
style={[
styles.subStepButtonBackText,
{color: Colors.secondary30.color},
]}>
Klik di sini untuk melihat informasi kondisi paspor
</Text>
</Pressable>
{previousPassportConditionOptions.map(option => (
<RadioButtonOptionComponent
key={option.value}
label={option.label}
description={option.description}
value={option.value}
selectedValue={selectedOption}
onSelect={setSelectedOption}
/>
))}
</View>
<Button
mode="contained"
onPress={() => {
(selectedOption === 'expired' || selectedOption === 'full_pages') &&
setSubStep(3);
(selectedOption === 'lost' ||
selectedOption === 'damaged' ||
selectedOption === 'lost_due_to_force_majeure' ||
selectedOption === 'damaged_due_to_force_majeure') &&
showLostOrDamagedPassportDialog();
}}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep2;

View File

@ -0,0 +1,76 @@
import React from 'react';
import {ScrollView, View, Pressable, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep3Props = {
setSubStep: (step: number) => void;
};
const Step2SupportingDocsSubStep3 = ({
setSubStep,
}: Step2SupportingDocsSubStep3Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => {
setSubStep(2);
}}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto Paspor Lama Anda (Halaman 2 Paspor)
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat jelas,
dan jangan gunakan foto dari Live Mode sebelum melanjutkan.
</Text>
</View>
<View style={styles.documentImage}>
<Text style={styles.documentImageSupportText}>
Foto Halaman 2 Paspor Lama
</Text>
<View
style={[
styles.documentImageCropped,
{backgroundColor: Colors.neutral100.color},
]}
/>
</View>
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(4)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Ambil Foto
</Button>
<Button
mode="outlined"
onPress={() => {}}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Upload Galeri
</Button>
</View>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep3;

View File

@ -0,0 +1,64 @@
import React from 'react';
import {ScrollView, View, Pressable, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep4Props = {
setSubStep: (step: number) => void;
};
const Step2SupportingDocsSubStep4 = ({
setSubStep,
}: Step2SupportingDocsSubStep4Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(3)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
marginBottom: 8,
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepTextWrapper}>
<Text style={styles.subStepTitle}>
Ambil/Upload Foto Paspor Lama Anda (Halaman 2 Paspor)
</Text>
<Text style={styles.subStepDesc}>
Pastikan pencahayaan cukup, tulisan pada identitas terlihat jelas,
dan jangan gunakan foto dari Live Mode sebelum melanjutkan.
</Text>
</View>
<View style={styles.documentImage} />
<View style={styles.subStepButtonContainer}>
<Button
mode="contained"
onPress={() => setSubStep(5)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Pilih Foto
</Button>
<Button
mode="outlined"
onPress={() => setSubStep(3)}
style={styles.subStepButtonOutlined}
textColor={Colors.primary30.color}>
Ulangi
</Button>
</View>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep4;

View File

@ -0,0 +1,64 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import TextInputComponent from '../../../../components/TextInput';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep5Props = {
setSubStep: (step: number) => void;
};
const Step2SupportingDocsSubStep5 = ({
setSubStep,
}: Step2SupportingDocsSubStep5Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(4)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Nomor paspor lama Anda"
placeholder="Masukkan nomor paspor lama Anda"
/>
<View>
<View style={styles.textInputBulletTextWrapper}>
<Text style={styles.textInputSupportText}></Text>
<Text style={styles.textInputSupportText}>
Nomor paspor lama minimal 7 karakter
</Text>
</View>
<View style={styles.textInputBulletTextWrapper}>
<Text style={styles.textInputSupportText}></Text>
<Text style={styles.textInputSupportText}>
Tulis nomor paspor tanpa menggunakan spasi. Contoh: B12345678
</Text>
</View>
</View>
</View>
<Button
mode="contained"
onPress={() => setSubStep(6)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep5;

View File

@ -0,0 +1,64 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import passportApplicationPurposeOptions from '../../../../data/Options/PassportApplicationPurposeOptions';
import styles from '../styles';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep6Props = {
setSubStep: (step: number) => void;
selectedOption: string;
setSelectedOption: (val: string) => void;
};
const Step2SupportingDocsSubStep6 = ({
setSubStep,
selectedOption,
setSelectedOption,
}: Step2SupportingDocsSubStep6Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(5)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Apakah tujuan Anda membuat paspor?
</Text>
{passportApplicationPurposeOptions.map(option => (
<RadioButtonOptionComponent
key={option.value}
label={option.label}
description={option.description}
value={option.value}
selectedValue={selectedOption}
onSelect={value => setSelectedOption(value)}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(7)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep6;

View File

@ -0,0 +1,69 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import TextInputComponent from '../../../../components/TextInput';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import destinationCountryOptions from '../../../../data/Options/DestinationCountryOptions';
import destinationCountryData from '../../../../data/DropdownData/DestinationCountryData';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep7Props = {
setSubStep: (step: number) => void;
selectedOption: string;
setSelectedOption: (val: string) => void;
};
const Step2SupportingDocsSubStep7 = ({
setSubStep,
selectedOption,
setSelectedOption,
}: Step2SupportingDocsSubStep7Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(6)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Negara mana yang akan Anda tuju?"
placeholder="Masukkan negara tujuan"
isDropdown
dropdownItemData={destinationCountryData}
/>
{destinationCountryOptions.map(option => (
<RadioButtonOptionComponent
key={option.value}
label={option.label}
description={option.description}
value={option.value}
selectedValue={selectedOption}
onSelect={value => setSelectedOption(value)}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(8)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep7;

View File

@ -0,0 +1,53 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import TextInputComponent from '../../../../components/TextInput';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep8Props = {
setSubStep: (step: number) => void;
};
const Step2SupportingDocsSubStep8 = ({
setSubStep,
}: Step2SupportingDocsSubStep8Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(7)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<TextInputComponent
title="Di mana tempat tinggal Anda di negara tujuan?"
placeholder="Masukkan alamat"
supportText="0/100 karakter"
containerHeight={90}
isMultiline
/>
</View>
<Button
mode="contained"
onPress={() => setSubStep(9)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep8;

View File

@ -0,0 +1,64 @@
import React from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import {Button} from 'react-native-paper';
import styles from '../styles';
import durationAbroadOptions from '../../../../data/Options/DurationAbroadOptions';
import RadioButtonOptionComponent from '../../../../components/RadioButtonOption';
import Colors from '../../../../../assets/styles/Colors';
type Step2SupportingDocsSubStep9Props = {
setSubStep: (step: number) => void;
selectedOption: string;
setSelectedOption: (value: string) => void;
};
const Step2SupportingDocsSubStep9 = ({
setSubStep,
selectedOption,
setSelectedOption,
}: Step2SupportingDocsSubStep9Props) => {
return (
<ScrollView>
<View style={styles.subStepContainer}>
<Pressable
onPress={() => setSubStep(8)}
style={({pressed}) => [
styles.subStepButtonBackWrapper,
{
transform: [{scale: pressed ? 0.99 : 1}],
},
]}>
<Icon name="chevron-left" size={24} />
<Text style={styles.subStepButtonBackText}>Kembali</Text>
</Pressable>
<View style={styles.subStepQuestionnaireOptionContainer}>
<Text style={styles.questionnaireData}>
Berapa lama Anda berencana berada di luar negeri?
</Text>
{durationAbroadOptions.map(options => (
<RadioButtonOptionComponent
key={options.value}
label={options.label}
description={options.description}
value={options.value}
selectedValue={selectedOption}
onSelect={value => setSelectedOption(value)}
/>
))}
</View>
<Button
mode="contained"
onPress={() => setSubStep(10)}
style={styles.subStepButtonContained}
textColor={Colors.neutral100.color}>
Lanjut
</Button>
</View>
</ScrollView>
);
};
export default Step2SupportingDocsSubStep9;

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, {useState} from 'react';
import {ScrollView, View, Text, Pressable} from 'react-native';
import styles from '../styles';
import Colors from '../../../../../assets/styles/Colors';
@ -15,11 +15,13 @@ interface BackButtonProps {
interface DocumentUploadSectionProps {
title: string;
isRequired?: boolean;
isIcon?: boolean;
}
interface Step3PaymentProps {
setStep: (step: number) => void;
setSubStep: (subStep: number) => void;
selectedPassportOption: string;
}
const BackButton = (props: BackButtonProps) => {
@ -41,39 +43,90 @@ const BackButton = (props: BackButtonProps) => {
};
const DocumentUploadSection = (props: DocumentUploadSectionProps) => {
const {title, isRequired = false} = props;
const {title, isRequired, isIcon} = props;
const [uploadedFileName, setUploadedFileName] = useState<string | null>(null);
const handleUpload = (p0: string) => {
let fileName = `${title.toLowerCase().replace(/ /g, '')}.jpg`;
if (
title === 'Akta kelahiran/ijazah/akta perkawinan/buku nikah/surat baptis'
) {
fileName = 'ijazah.jpg';
}
setUploadedFileName(fileName);
};
const handleDelete = () => {
setUploadedFileName(null);
};
return (
<View>
<Text style={styles.subStepSectionButtonTextTitle}>
{title}{' '}
{isRequired && (
<Text style={{color: Colors.indicatorRed.color}}>*</Text>
<View style={styles.subStepRowTextButton}>
<Text style={styles.subStepSectionButtonTextTitle}>
{title}{' '}
{isRequired && (
<Text style={{color: Colors.indicatorRed.color}}>*</Text>
)}
</Text>
{isIcon && (
<Icon name="information" size={24} color={Colors.primary30.color} />
)}
</Text>
<View style={styles.sectionButtonWrapper}>
<Button
icon="camera-outline"
mode="contained"
style={styles.buttonContainedSecondary}
textColor={Colors.neutral100.color}
labelStyle={{fontSize: 12}}>
Foto Dokumen
</Button>
<Button
icon="tray-arrow-up"
mode="contained"
style={styles.buttonContainedSecondary}
textColor={Colors.neutral100.color}
labelStyle={{fontSize: 12}}>
Unggah Dokumen
</Button>
</View>
{!uploadedFileName ? (
<View style={styles.sectionButtonWrapper}>
<Button
icon="camera-outline"
mode="contained"
style={styles.buttonContainedSecondary}
textColor={Colors.neutral100.color}
labelStyle={{fontSize: 12}}
onPress={() =>
handleUpload(`${title.toLowerCase().replace(/ /g, '')}.jpg`)
}>
Foto Dokumen
</Button>
<Button
icon="tray-arrow-up"
mode="contained"
style={styles.buttonContainedSecondary}
textColor={Colors.neutral100.color}
labelStyle={{fontSize: 12}}
onPress={() =>
handleUpload(`${title.toLowerCase().replace(/ /g, '')}.jpg`)
}>
Unggah Dokumen
</Button>
</View>
) : (
<View style={styles.subStepUploadedDocumentContainer}>
<View style={styles.subStepUploadedDocumentTextWrapper}>
<Text style={styles.subStepUploadedDocumentTitle}>
Berhasil dipilih
</Text>
<Text style={styles.subStepUploadedDocumentDesc}>
{uploadedFileName}
</Text>
</View>
<Icon
name="trash-can-outline"
size={24}
color={Colors.indicatorRed.color}
onPress={handleDelete}
/>
</View>
)}
</View>
);
};
const Step3Payment = (props: Step3PaymentProps) => {
const {setStep, setSubStep} = props;
const {setStep, setSubStep, selectedPassportOption} = props;
console.log('selectedPassportOption', selectedPassportOption);
return (
<ScrollView>
<View style={styles.subStepContainer}>
@ -87,7 +140,13 @@ const Step3Payment = (props: Step3PaymentProps) => {
<View style={{marginBottom: 16, gap: 4}}>
<Text style={styles.subStepDesc}>
Layanan yang cocok untuk Anda adalah{' '}
<Text style={{...FontFamily.notoSansBold}}>Paspor Penggantian</Text>
{selectedPassportOption !== 'already' ? (
<Text style={{...FontFamily.notoSansBold}}>
Paspor Penggantian
</Text>
) : (
<Text style={{...FontFamily.notoSansBold}}>Paspor Baru</Text>
)}
. Silakan unggah kelengkapan dokumen berikut.
</Text>
<View>
@ -166,8 +225,13 @@ const Step3Payment = (props: Step3PaymentProps) => {
<View style={styles.subStepSectionButtonContainer}>
<DocumentUploadSection title="e-KTP" isRequired />
<DocumentUploadSection title="Kartu Keluarga" />
<DocumentUploadSection title="Akta kelahiran/ijazah/akta perkawinan/buku nikah/surat baptis" />
<DocumentUploadSection title="Paspor Lama" isRequired />
<DocumentUploadSection
title="Akta kelahiran/ijazah/akta perkawinan/buku nikah/surat baptis"
isIcon
/>
{selectedPassportOption !== 'already' && (
<DocumentUploadSection title="Paspor Lama" isRequired />
)}
</View>
<Button

View File

@ -102,6 +102,42 @@ const styles = StyleSheet.create({
alignItems: 'center',
gap: 8,
},
textInputSupportText: {
fontSize: 10,
...FontFamily.notoSansRegular,
color: '#8F9098',
},
questionnaireData: {
...FontFamily.notoSansBold,
fontSize: 14,
color: Colors.primary30.color,
includeFontPadding: false,
},
documentImageContainer: {
alignItems: 'center',
},
documentImage: {
alignItems: 'center',
justifyContent: 'center',
marginVertical: 16,
height: 350,
backgroundColor: Colors.primary70.color,
borderRadius: 20,
},
documentImageSupportText: {
...FontFamily.notoSansRegular,
color: Colors.neutral100.color,
includeFontPadding: false,
fontSize: 14,
marginBottom: 10,
},
documentImageCropped: {
marginBottom: 16,
width: 225,
height: 140,
backgroundColor: Colors.primary70.color,
borderRadius: 8,
},
questionnaireDataSecondary: {
...FontFamily.notoSansBold,
fontSize: 12,
@ -234,7 +270,36 @@ const styles = StyleSheet.create({
},
accordionTextContentAlphabetWrapper: {
marginStart: 16,
}
},
subStepUploadedDocumentContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderWidth: 1,
borderColor: Colors.secondary50.color,
borderRadius: 8,
paddingHorizontal: 16,
paddingVertical: 8,
},
subStepUploadedDocumentTextWrapper: {
gap: 4,
},
subStepUploadedDocumentTitle: {
includeFontPadding: false,
color: Colors.primary30.color,
fontSize: 12,
...FontFamily.notoSansMedium,
},
subStepUploadedDocumentDesc: {
includeFontPadding: false,
color: Colors.primary40.color,
fontSize: 10,
...FontFamily.notoSansRegular,
},
subStepRowTextButton: {
flexDirection: 'row',
alignItems: 'center',
},
});
export default styles;