index.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. import React, { useEffect, useState, useRef } from 'react';
  2. import { View, Text, TouchableOpacity, ScrollView, Alert } from 'react-native';
  3. import ReactModal from 'react-native-modal';
  4. import { useNavigation } from '@react-navigation/native';
  5. import { Picker as WheelPicker } from 'react-native-wheel-pick';
  6. import moment from 'moment';
  7. import ActionSheet from 'react-native-actions-sheet';
  8. import { PageWrapper, Header, Input, WarningModal } from 'src/components';
  9. import RegionItem from '../Components/RegionItem';
  10. import RangeCalendar from 'src/components/Calendars/RangeCalendar';
  11. import { StoreType, storage } from 'src/storage';
  12. import { Colors } from 'src/theme';
  13. import { NAVIGATION_PAGES } from 'src/types';
  14. import { RegionAddData } from '../utils/types';
  15. import {
  16. useGetTripQuery,
  17. usePostDeleteTripMutation,
  18. usePostUpdateTripMutation,
  19. usePostSetNewTripMutation
  20. } from '@api/trips';
  21. import { qualityOptions } from '../utils/constants';
  22. import { styles } from './styles';
  23. import CalendarSvg from '../../../../../assets/icons/calendar.svg';
  24. import { ActivityIndicator } from 'react-native-paper';
  25. interface DateValue {
  26. year: number | null;
  27. month: number | null;
  28. day: number | null;
  29. }
  30. interface RegionWithDates extends RegionAddData {
  31. visitStartDate?: DateValue | null;
  32. visitEndDate?: DateValue | null;
  33. year_from?: number;
  34. year_to?: number;
  35. month_from?: number;
  36. month_to?: number;
  37. day_from?: number | null;
  38. day_to?: number | null;
  39. }
  40. interface DatePickerState {
  41. regionIndex: number;
  42. field: 'visitStartDate' | 'visitEndDate';
  43. }
  44. const AddNewTripScreen = ({ route }: { route: any }) => {
  45. const editTripId = route.params?.editTripId ?? null;
  46. const token = storage.get('token', StoreType.STRING) as string;
  47. const { data: editData } = useGetTripQuery(token, editTripId, Boolean(editTripId));
  48. const navigation = useNavigation();
  49. const [calendarVisible, setCalendarVisible] = useState(false);
  50. const [selectedDates, setSelectedDates] = useState<string | null>(null);
  51. const [description, setDescription] = useState<string>('');
  52. const [regions, setRegions] = useState<RegionWithDates[] | null>(null);
  53. const [disabled, setDisabled] = useState(true);
  54. const [isLoading, setIsLoading] = useState<string | null>(null);
  55. const [qualitySelectorVisible, setQualitySelectorVisible] = useState(false);
  56. const [selectedRegionId, setSelectedRegionId] = useState<number | null>(null);
  57. const [isWarningModalVisible, setIsWarningModalVisible] = useState(false);
  58. const [showDatePicker, setShowDatePicker] = useState<DatePickerState | null>(null);
  59. const actionSheetRef = useRef<any>(null);
  60. const [selectedYear, setSelectedYear] = useState<number | null>(new Date().getFullYear());
  61. const [selectedMonth, setSelectedMonth] = useState<number | null>(new Date().getMonth() + 1);
  62. const [selectedDay, setSelectedDay] = useState<number | null>(null);
  63. const [pendingDelete, setPendingDelete] = useState(false);
  64. const { mutate: saveNewTrip } = usePostSetNewTripMutation();
  65. const { mutate: updateTrip } = usePostUpdateTripMutation();
  66. const { mutate: deleteTrip } = usePostDeleteTripMutation();
  67. const fillRegionDatesFromSelectedDates = (regionsToUpdate: RegionWithDates[]) => {
  68. if (!selectedDates || !regionsToUpdate) return regionsToUpdate;
  69. const from = selectedDates.split(' - ')[0];
  70. const to = selectedDates.split(' - ')[1];
  71. const updatedRegions = regionsToUpdate.map((region) => {
  72. const hasEmptyStartDate = !region.visitStartDate?.year || !region.visitStartDate?.month;
  73. const hasEmptyEndDate = !region.visitEndDate?.year || !region.visitEndDate?.month;
  74. if (hasEmptyStartDate || hasEmptyEndDate) {
  75. const updatedRegion = { ...region };
  76. if (hasEmptyStartDate) {
  77. updatedRegion.visitStartDate = {
  78. year: moment(from, 'YYYY-MM-DD').year(),
  79. month: moment(from, 'YYYY-MM-DD').month() + 1,
  80. day: null
  81. };
  82. updatedRegion.year_from = moment(from, 'YYYY-MM-DD').year();
  83. updatedRegion.month_from = moment(from, 'YYYY-MM-DD').month() + 1;
  84. }
  85. if (hasEmptyEndDate) {
  86. updatedRegion.visitEndDate = {
  87. year: moment(to, 'YYYY-MM-DD').year(),
  88. month: moment(to, 'YYYY-MM-DD').month() + 1,
  89. day: null
  90. };
  91. updatedRegion.year_to = moment(to, 'YYYY-MM-DD').year();
  92. updatedRegion.month_to = moment(to, 'YYYY-MM-DD').month() + 1;
  93. }
  94. return updatedRegion;
  95. }
  96. return region;
  97. });
  98. return updatedRegions;
  99. };
  100. useEffect(() => {
  101. if (route.params?.regionsToSave) {
  102. setRegions((currentRegions) => {
  103. const newRegionsIds = route.params.regionsToSave.map((region: RegionAddData) => region.id);
  104. const existingRegions = currentRegions?.filter((region) =>
  105. newRegionsIds.includes(region.id)
  106. );
  107. const updatedRegions = route.params.regionsToSave.map((newRegion: RegionAddData) => {
  108. const existingRegion = existingRegions?.find((region) => region.id === newRegion.id);
  109. return {
  110. ...newRegion,
  111. quality: existingRegion ? existingRegion.quality : 3,
  112. can_be_hidden: existingRegion ? existingRegion.can_be_hidden : newRegion.hidden,
  113. hidden: existingRegion ? existingRegion.hidden : false,
  114. visitStartDate: existingRegion?.visitStartDate || {
  115. year: null,
  116. month: null,
  117. day: null
  118. },
  119. visitEndDate: existingRegion?.visitEndDate || {
  120. year: null,
  121. month: null,
  122. day: null
  123. }
  124. };
  125. });
  126. return fillRegionDatesFromSelectedDates(updatedRegions);
  127. });
  128. }
  129. }, [route.params?.regionsToSave]);
  130. function extractNumberAndExtension(path: string | null) {
  131. if (!path) return null;
  132. const slashIndex = path.lastIndexOf('/');
  133. return path.substring(slashIndex + 1);
  134. }
  135. useEffect(() => {
  136. if (editData && editData.trip) {
  137. setSelectedDates(editData.trip.date_from + ' - ' + editData.trip.date_to);
  138. setDescription(editData.trip.description);
  139. setRegions(
  140. editData.trip.regions.map((region: any) => {
  141. return {
  142. ...region,
  143. id: region.region,
  144. flag1: extractNumberAndExtension(region.flag1),
  145. flag2: extractNumberAndExtension(region.flag2),
  146. visitStartDate: {
  147. year: region.year_from || null,
  148. month: region.month_from || null,
  149. day: region.day_from || null
  150. },
  151. visitEndDate: {
  152. year: region.year_to || null,
  153. month: region.month_to || null,
  154. day: region.day_to || null
  155. }
  156. };
  157. })
  158. );
  159. }
  160. }, [editData]);
  161. useEffect(() => {
  162. if (regions?.length && selectedDates) {
  163. setRegions((currentRegions) => {
  164. if (!currentRegions) return null;
  165. return fillRegionDatesFromSelectedDates(currentRegions);
  166. });
  167. setDisabled(false);
  168. } else {
  169. setDisabled(true);
  170. }
  171. }, [selectedDates]);
  172. useEffect(() => {
  173. setDisabled(!(regions?.length && selectedDates));
  174. }, [regions, selectedDates]);
  175. const currentYear = new Date().getFullYear();
  176. const years = ['-', ...Array.from({ length: 120 }, (_, i) => (currentYear - 80 + i).toString())];
  177. const getAvailableMonths = (year: number | null) => {
  178. const allMonths = [
  179. { label: '-', value: null },
  180. { label: 'Jan', value: 1 },
  181. { label: 'Feb', value: 2 },
  182. { label: 'Mar', value: 3 },
  183. { label: 'Apr', value: 4 },
  184. { label: 'May', value: 5 },
  185. { label: 'Jun', value: 6 },
  186. { label: 'Jul', value: 7 },
  187. { label: 'Aug', value: 8 },
  188. { label: 'Sep', value: 9 },
  189. { label: 'Oct', value: 10 },
  190. { label: 'Nov', value: 11 },
  191. { label: 'Dec', value: 12 }
  192. ];
  193. return allMonths;
  194. };
  195. const months = getAvailableMonths(selectedYear);
  196. const getDaysInMonth = (
  197. year: number | null,
  198. month: number | null
  199. ): Array<{ label: string; value: number | null }> => {
  200. if (!year || !month) return [{ label: '-', value: null }];
  201. const daysCount = moment(`${year}-${month}`, 'YYYY-M').daysInMonth();
  202. const days = [{ label: '-', value: null }];
  203. for (let i = 1; i <= daysCount; i++) {
  204. days.push({ label: i.toString(), value: i as never });
  205. }
  206. return days;
  207. };
  208. const days = getDaysInMonth(selectedYear, selectedMonth);
  209. const openDatePicker = (
  210. index: number,
  211. field: 'visitStartDate' | 'visitEndDate',
  212. initialDate?: DateValue | null
  213. ) => {
  214. setShowDatePicker({ regionIndex: index, field });
  215. if (initialDate && initialDate.year) {
  216. setSelectedYear(initialDate.year || null);
  217. setSelectedMonth(initialDate.month || null);
  218. setSelectedDay(initialDate.day || null);
  219. } else {
  220. setSelectedYear(null);
  221. setSelectedMonth(null);
  222. setSelectedDay(null);
  223. }
  224. actionSheetRef.current?.show();
  225. };
  226. const handleDateConfirm = () => {
  227. if (showDatePicker) {
  228. const { regionIndex, field } = showDatePicker;
  229. const dateValue: DateValue = {
  230. year: selectedYear || null,
  231. month: selectedMonth || null,
  232. day: selectedDay || null
  233. };
  234. setRegions((prev) => {
  235. if (!prev) return null;
  236. const newRegions = [...prev];
  237. newRegions[regionIndex] = { ...newRegions[regionIndex], [field]: dateValue };
  238. return newRegions;
  239. });
  240. setShowDatePicker(null);
  241. actionSheetRef.current?.hide();
  242. }
  243. };
  244. const handleDateCancel = () => {
  245. setShowDatePicker(null);
  246. actionSheetRef.current?.hide();
  247. };
  248. const changeQualityForRegion = (index: number | null, newQuality: number) => {
  249. if (index === null || index === undefined) return;
  250. regions &&
  251. setRegions((prev) => {
  252. if (!prev) return null;
  253. const newRegions = [...prev];
  254. newRegions[index] = { ...newRegions[index], quality: newQuality };
  255. return newRegions;
  256. });
  257. };
  258. const changeHiddenForRegion = (index: number | null) => {
  259. if (index === null || index === undefined) return;
  260. regions &&
  261. setRegions((prev) => {
  262. if (!prev) return null;
  263. const newRegions = [...prev];
  264. newRegions[index] = { ...newRegions[index], hidden: !newRegions[index].hidden };
  265. return newRegions;
  266. });
  267. };
  268. const duplicateRegion = (index: number) => {
  269. if (!regions) return;
  270. const regionToCopy = regions[index];
  271. const copy = { ...regionToCopy };
  272. const newRegions = [...regions];
  273. newRegions.splice(index + 1, 0, copy);
  274. setRegions(newRegions);
  275. };
  276. const moveRegionUp = (index: number) => {
  277. if (index <= 0 || !regions) return;
  278. const newRegions = [...regions];
  279. [newRegions[index - 1], newRegions[index]] = [newRegions[index], newRegions[index - 1]];
  280. setRegions(newRegions);
  281. };
  282. const moveRegionDown = (index: number) => {
  283. if (!regions || index >= regions.length - 1) return;
  284. const newRegions = [...regions];
  285. [newRegions[index + 1], newRegions[index]] = [newRegions[index], newRegions[index + 1]];
  286. setRegions(newRegions);
  287. };
  288. const handleDeleteRegion = (index: number) => {
  289. if (!regions) return;
  290. const updated = [...regions];
  291. updated.splice(index, 1);
  292. setRegions(updated);
  293. };
  294. const handleDeleteTrip = async () => {
  295. setIsWarningModalVisible(false);
  296. setPendingDelete(true);
  297. };
  298. const handleSaveNewTrip = () => {
  299. if (regions && selectedDates) {
  300. setIsLoading('save');
  301. const regionsData = regions.map((region) => {
  302. return {
  303. id: region.id,
  304. quality: region.quality ?? 3,
  305. hidden: region.hidden,
  306. year_from: region.visitStartDate?.year || null,
  307. year_to: region.visitEndDate?.year || null,
  308. month_from: region.visitStartDate?.month || null,
  309. month_to: region.visitEndDate?.month || null,
  310. day_from: region.visitStartDate?.day || null,
  311. day_to: region.visitEndDate?.day || null
  312. };
  313. });
  314. if (regionsData.length > 30) {
  315. Alert.alert('One trip cannot have more than 30 regions.');
  316. setIsLoading(null);
  317. return;
  318. }
  319. saveNewTrip(
  320. {
  321. token,
  322. date_from: selectedDates.split(' - ')[0],
  323. date_to: selectedDates.split(' - ')[1],
  324. description,
  325. regions: regionsData
  326. },
  327. {
  328. onSuccess: (res) => {
  329. if (res && res.result === 'OK') {
  330. navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { saved: true }] as never));
  331. }
  332. setIsLoading(null);
  333. },
  334. onError: () => {
  335. setIsLoading(null);
  336. }
  337. }
  338. );
  339. }
  340. };
  341. const handleUpdateTrip = () => {
  342. if (regions && selectedDates) {
  343. setIsLoading('update');
  344. const regionsData = regions.map((region) => {
  345. return {
  346. id: region.id,
  347. quality: region.quality ?? 3,
  348. hidden: region.hidden,
  349. year_from: region.visitStartDate?.year || null,
  350. year_to: region.visitEndDate?.year || null,
  351. month_from: region.visitStartDate?.month || null,
  352. month_to: region.visitEndDate?.month || null,
  353. day_from: region.visitStartDate?.day || null,
  354. day_to: region.visitEndDate?.day || null
  355. };
  356. });
  357. if (regionsData.length > 30) {
  358. Alert.alert('One trip cannot have more than 30 regions.');
  359. setIsLoading(null);
  360. return;
  361. }
  362. updateTrip(
  363. {
  364. token,
  365. trip_id: editTripId,
  366. date_from: selectedDates.split(' - ')[0],
  367. date_to: selectedDates.split(' - ')[1],
  368. description,
  369. regions: regionsData
  370. },
  371. {
  372. onSuccess: (res) => {
  373. if (res && res.result === 'OK') {
  374. navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { updated: true }] as never));
  375. }
  376. setIsLoading(null);
  377. },
  378. onError: () => {
  379. setIsLoading(null);
  380. }
  381. }
  382. );
  383. }
  384. };
  385. return (
  386. <PageWrapper style={{ flex: 1 }}>
  387. <Header label={editTripId ? 'Edit Trip' : 'Add New Trip'} />
  388. <ScrollView
  389. contentContainerStyle={{ flexGrow: 1, gap: 16 }}
  390. showsVerticalScrollIndicator={false}
  391. >
  392. <TouchableOpacity style={styles.regionSelector} onPress={() => setCalendarVisible(true)}>
  393. <CalendarSvg fill={Colors.LIGHT_GRAY} />
  394. <Text style={styles.regionText}>{selectedDates ?? 'Add dates'}</Text>
  395. </TouchableOpacity>
  396. <Input
  397. placeholder="Add description and all interesting moments of your trip"
  398. inputMode={'text'}
  399. onChange={(text) => setDescription(text)}
  400. value={description}
  401. header="Description"
  402. height={54}
  403. multiline={true}
  404. />
  405. <View style={{ marginBottom: 8 }}>
  406. <Text style={styles.regionsLabel}>Regions</Text>
  407. <TouchableOpacity
  408. style={styles.addRegionBtn}
  409. onPress={() =>
  410. navigation.navigate(
  411. ...([
  412. NAVIGATION_PAGES.ADD_REGIONS,
  413. { regionsParams: regions, editId: editTripId }
  414. ] as never)
  415. )
  416. }
  417. >
  418. <Text style={styles.addRegionBtntext}>Add Region</Text>
  419. </TouchableOpacity>
  420. {regions && regions.length ? (
  421. <View style={styles.regionsContainer}>
  422. {regions.map((region, index) => {
  423. return (
  424. <RegionItem
  425. key={`${region.id}-${index}`}
  426. region={region}
  427. index={index}
  428. total={regions.length}
  429. onDelete={() => handleDeleteRegion(index)}
  430. onQualityChange={() => {
  431. setSelectedRegionId(index);
  432. setQualitySelectorVisible(true);
  433. }}
  434. onHiddenChange={() => changeHiddenForRegion(index)}
  435. openDatePicker={openDatePicker}
  436. visitStartDate={region.visitStartDate}
  437. visitEndDate={region.visitEndDate}
  438. onDuplicate={() => duplicateRegion(index)}
  439. onMoveUp={() => moveRegionUp(index)}
  440. onMoveDown={() => moveRegionDown(index)}
  441. />
  442. );
  443. })}
  444. </View>
  445. ) : (
  446. <Text style={styles.noRegiosText}>No regions at the moment</Text>
  447. )}
  448. </View>
  449. </ScrollView>
  450. <View style={styles.tabContainer}>
  451. {editTripId ? (
  452. <>
  453. <TouchableOpacity
  454. style={[styles.tabStyle, styles.deleteTab]}
  455. onPress={() => setIsWarningModalVisible(true)}
  456. disabled={isLoading === 'delete'}
  457. >
  458. {isLoading === 'delete' ? (
  459. <ActivityIndicator size={18} color={Colors.RED} />
  460. ) : (
  461. <Text style={[styles.tabText, styles.deleteTabText]}>Delete Trip</Text>
  462. )}
  463. </TouchableOpacity>
  464. <TouchableOpacity
  465. style={[
  466. styles.tabStyle,
  467. styles.addNewTab,
  468. disabled && { backgroundColor: Colors.LIGHT_GRAY, borderColor: Colors.LIGHT_GRAY }
  469. ]}
  470. onPress={handleUpdateTrip}
  471. disabled={disabled || isLoading === 'update'}
  472. >
  473. {isLoading === 'update' ? (
  474. <ActivityIndicator size={18} color={Colors.WHITE} />
  475. ) : (
  476. <Text style={[styles.tabText, styles.addNewTabText]}>Save Trip</Text>
  477. )}
  478. </TouchableOpacity>
  479. </>
  480. ) : (
  481. <TouchableOpacity
  482. style={[
  483. styles.tabStyle,
  484. styles.addNewTab,
  485. disabled && { backgroundColor: Colors.LIGHT_GRAY, borderColor: Colors.LIGHT_GRAY },
  486. { paddingVertical: 12 }
  487. ]}
  488. onPress={handleSaveNewTrip}
  489. disabled={disabled || isLoading === 'save'}
  490. >
  491. {isLoading === 'save' ? (
  492. <ActivityIndicator size={18} color={Colors.WHITE} />
  493. ) : (
  494. <Text style={[styles.tabText, styles.addNewTabText]}>Add New Trip</Text>
  495. )}
  496. </TouchableOpacity>
  497. )}
  498. </View>
  499. <ActionSheet
  500. ref={actionSheetRef}
  501. gestureEnabled={false}
  502. headerAlwaysVisible={true}
  503. onTouchBackdrop={handleDateConfirm}
  504. CustomHeaderComponent={
  505. <View style={styles.datePickerHeader}>
  506. <TouchableOpacity onPress={handleDateCancel}>
  507. <Text style={styles.datePickerCancel}>Cancel</Text>
  508. </TouchableOpacity>
  509. <Text style={styles.datePickerTitle}>Select Date</Text>
  510. <TouchableOpacity onPress={handleDateConfirm}>
  511. <Text style={styles.datePickerConfirm}>Done</Text>
  512. </TouchableOpacity>
  513. </View>
  514. }
  515. >
  516. <View style={styles.wheelContainer}>
  517. <View style={styles.wheelColumn}>
  518. <Text style={styles.wheelLabel}>Day</Text>
  519. <WheelPicker
  520. style={styles.wheelPicker}
  521. textColor={Colors.DARK_BLUE}
  522. itemStyle={{ fontSize: 16, fontFamily: 'montserrat-600', padding: 0 }}
  523. pickerData={days?.map((d) => d.label)}
  524. selectedValue={days?.find((d) => d.value === selectedDay)?.label || '-'}
  525. onValueChange={(value: string) => {
  526. const day = days?.find((d) => d.label === value);
  527. setSelectedDay(day?.value || null);
  528. }}
  529. />
  530. </View>
  531. <View style={styles.wheelColumn}>
  532. <Text style={styles.wheelLabel}>Month</Text>
  533. <WheelPicker
  534. style={styles.wheelPicker}
  535. textColor={Colors.DARK_BLUE}
  536. itemStyle={{
  537. fontSize: 16,
  538. fontFamily: 'montserrat-600'
  539. }}
  540. pickerData={months ? months?.map((m) => m.label) : []}
  541. selectedValue={months.find((m) => m.value === selectedMonth)?.label || '-'}
  542. onValueChange={(value: string) => {
  543. const month = months?.find((m) => m.label === value);
  544. setSelectedMonth(month?.value || null);
  545. if (!month?.value) setSelectedDay(null);
  546. }}
  547. />
  548. </View>
  549. <View style={styles.wheelColumn}>
  550. <Text style={styles.wheelLabel}>Year</Text>
  551. <WheelPicker
  552. style={styles.wheelPicker}
  553. textColor={Colors.DARK_BLUE}
  554. itemStyle={{ fontSize: 16, fontFamily: 'montserrat-600' }}
  555. pickerData={years}
  556. selectedValue={selectedYear ? selectedYear.toString() : '-'}
  557. onValueChange={(value: string) => {
  558. if (value === '-') {
  559. setSelectedYear(null);
  560. setSelectedMonth(null);
  561. setSelectedDay(null);
  562. } else {
  563. setSelectedYear(Number(value));
  564. }
  565. }}
  566. />
  567. </View>
  568. </View>
  569. </ActionSheet>
  570. <RangeCalendar
  571. isModalVisible={calendarVisible}
  572. closeModal={(startDate?: string | null, endDate?: string | null) => {
  573. startDate &&
  574. setSelectedDates(
  575. startDate.toString() + ' - ' + (endDate ? endDate?.toString() : startDate?.toString())
  576. );
  577. setCalendarVisible(false);
  578. }}
  579. />
  580. <ReactModal
  581. isVisible={qualitySelectorVisible}
  582. onBackdropPress={() => setQualitySelectorVisible(false)}
  583. style={styles.modal}
  584. statusBarTranslucent={true}
  585. presentationStyle="overFullScreen"
  586. >
  587. <View style={styles.wrapper}>
  588. <View style={{ paddingBottom: 16 }}>
  589. {qualityOptions.map((option) => (
  590. <TouchableOpacity
  591. key={option.id}
  592. style={styles.btnOption}
  593. onPress={() => {
  594. setQualitySelectorVisible(false);
  595. changeQualityForRegion(selectedRegionId, option.id);
  596. }}
  597. >
  598. <Text style={styles.btnOptionText}>{option.name}</Text>
  599. </TouchableOpacity>
  600. ))}
  601. </View>
  602. </View>
  603. </ReactModal>
  604. <WarningModal
  605. type={'delete'}
  606. isVisible={isWarningModalVisible}
  607. onClose={() => setIsWarningModalVisible(false)}
  608. title="Delete Trip"
  609. message="Are you sure you want to delete your trip?"
  610. action={handleDeleteTrip}
  611. onModalHide={() => {
  612. if (pendingDelete) {
  613. setPendingDelete(false);
  614. setIsLoading('delete');
  615. deleteTrip(
  616. {
  617. token,
  618. trip_id: editTripId
  619. },
  620. {
  621. onSuccess: (res) => {
  622. if (res && res.result === 'OK') {
  623. navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { deleted: true }] as never));
  624. }
  625. setIsLoading(null);
  626. },
  627. onError: () => {
  628. setIsLoading(null);
  629. }
  630. }
  631. );
  632. }
  633. }}
  634. />
  635. </PageWrapper>
  636. );
  637. };
  638. export default AddNewTripScreen;