Browse Source

event fixes

Viktoriia 1 month ago
parent
commit
f8b10cf03d

+ 10 - 0
assets/icons/events/edit.svg

@@ -0,0 +1,10 @@
+<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_1699_18642)">
+<path d="M16.5797 0.762988C15.8098 -0.0069336 14.5652 -0.0069336 13.7953 0.762988L12.7371 1.81768L16.1789 5.25947L17.2371 4.20127C18.007 3.43135 18.007 2.18682 17.2371 1.41689L16.5797 0.762988ZM6.06094 8.49736C5.84648 8.71182 5.68125 8.97549 5.58633 9.26729L4.5457 12.3892C4.44375 12.6915 4.52461 13.0255 4.74961 13.254C4.97461 13.4825 5.30859 13.5599 5.61445 13.4579L8.73633 12.4173C9.02461 12.3224 9.28828 12.1571 9.50625 11.9427L15.3879 6.05752L11.9426 2.61221L6.06094 8.49736ZM3.375 2.2501C1.51172 2.2501 0 3.76182 0 5.6251V14.6251C0 16.4884 1.51172 18.0001 3.375 18.0001H12.375C14.2383 18.0001 15.75 16.4884 15.75 14.6251V11.2501C15.75 10.6278 15.2473 10.1251 14.625 10.1251C14.0027 10.1251 13.5 10.6278 13.5 11.2501V14.6251C13.5 15.2474 12.9973 15.7501 12.375 15.7501H3.375C2.75273 15.7501 2.25 15.2474 2.25 14.6251V5.6251C2.25 5.00283 2.75273 4.5001 3.375 4.5001H6.75C7.37227 4.5001 7.875 3.99736 7.875 3.3751C7.875 2.75283 7.37227 2.2501 6.75 2.2501H3.375Z"/>
+</g>
+<defs>
+<clipPath id="clip0_1699_18642">
+<rect width="18" height="18" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 8 - 4
src/components/Calendar/InputTimePicker/index.tsx

@@ -14,13 +14,17 @@ type Props = {
   formikError?: string | boolean;
   formikError?: string | boolean;
   headerTitle?: string;
   headerTitle?: string;
   defaultTime?: Date | null;
   defaultTime?: Date | null;
+  placeholder?: string;
+  inputHeader?: string;
 };
 };
 
 
 export const InputTimePicker: FC<Props> = ({
 export const InputTimePicker: FC<Props> = ({
   selectedTime,
   selectedTime,
   formikError,
   formikError,
   headerTitle,
   headerTitle,
-  defaultTime
+  defaultTime,
+  placeholder,
+  inputHeader
 }) => {
 }) => {
   const [visible, setVisible] = useState(false);
   const [visible, setVisible] = useState(false);
   const [spinnerSelectedTime, setSpinnerSelectedTime] = useState<Date | null>(defaultTime ?? null);
   const [spinnerSelectedTime, setSpinnerSelectedTime] = useState<Date | null>(defaultTime ?? null);
@@ -41,10 +45,10 @@ export const InputTimePicker: FC<Props> = ({
   };
   };
 
 
   return (
   return (
-    <View>
+    <View style={{ flex: 1 }}>
       <Input
       <Input
         icon={<ClockIcon fill={Colors.LIGHT_GRAY} width={20} height={20} />}
         icon={<ClockIcon fill={Colors.LIGHT_GRAY} width={20} height={20} />}
-        header={'Time'}
+        header={inputHeader ?? 'Time'}
         value={
         value={
           defaultTime
           defaultTime
             ? defaultTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
             ? defaultTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
@@ -53,7 +57,7 @@ export const InputTimePicker: FC<Props> = ({
         isFocused={(b) => setVisible(b)}
         isFocused={(b) => setVisible(b)}
         onBlur={() => {}}
         onBlur={() => {}}
         inputMode={'none'}
         inputMode={'none'}
-        placeholder={'Choose a time'}
+        placeholder={placeholder ?? 'Choose a time'}
         formikError={formikError}
         formikError={formikError}
       />
       />
       <Modal
       <Modal

+ 33 - 4
src/modules/api/events/events-api.ts

@@ -26,8 +26,10 @@ export type SingleEvent = {
   available?: number;
   available?: number;
   joined: 0 | 1;
   joined: 0 | 1;
   visible?: 0 | 1;
   visible?: 0 | 1;
-  archived?: 0 | 1;
+  archived: 0 | 1;
   time?: string;
   time?: string;
+  time_from?: string;
+  time_to?: string;
 };
 };
 
 
 export type Participants = {
 export type Participants = {
@@ -66,6 +68,7 @@ export type EventSettings = {
     nm: number | null;
     nm: number | null;
     un: number | null;
     un: number | null;
   };
   };
+  nm_region?: number;
 };
 };
 
 
 export type EventAttachments = {
 export type EventAttachments = {
@@ -125,6 +128,21 @@ export interface PostGetPhotosForRegionReturn extends ResponseType {
   photos: number[];
   photos: number[];
 }
 }
 
 
+export interface PostGetEventForEditingReturn {
+  address1: string;
+  address2: string;
+  capacity: number | null;
+  date: string;
+  details: string;
+  lat: number | null;
+  lon: number;
+  region: number;
+  time_from: string;
+  time_to: string;
+  title: string;
+  result: string;
+}
+
 export interface PostJoinEvent {
 export interface PostJoinEvent {
   token: string;
   token: string;
   id: number;
   id: number;
@@ -170,9 +188,15 @@ export interface PostAddEvent {
   event: any;
   event: any;
 }
 }
 
 
+export interface PostUpdateEvent {
+  token: string;
+  event_id: number;
+  event: any;
+}
+
 export const eventsApi = {
 export const eventsApi = {
-  getEventsList: (token: string) =>
-    request.postForm<PostGetEventsListReturn>(API.GET_EVENTS_LIST, { token }),
+  getEventsList: (token: string, past: number) =>
+    request.postForm<PostGetEventsListReturn>(API.GET_EVENTS_LIST, { token, past }),
   getEvent: (token: string, url: string) =>
   getEvent: (token: string, url: string) =>
     request.postForm<PostGetEventReturn>(API.GET_EVENT, { token, url }),
     request.postForm<PostGetEventReturn>(API.GET_EVENT, { token, url }),
   joinEvent: (data: PostJoinEvent) => request.postForm<ResponseType>(API.JOIN_EVENT, data),
   joinEvent: (data: PostJoinEvent) => request.postForm<ResponseType>(API.JOIN_EVENT, data),
@@ -211,5 +235,10 @@ export const eventsApi = {
     request.postForm<PostGetCanAddEventReturn>(API.CAN_ADD_EVENT, { token }),
     request.postForm<PostGetCanAddEventReturn>(API.CAN_ADD_EVENT, { token }),
   getPhotosForRegion: (region_id: number) =>
   getPhotosForRegion: (region_id: number) =>
     request.postForm<PostGetPhotosForRegionReturn>(API.GET_PHOTOS_FOR_REGION, { region_id }),
     request.postForm<PostGetPhotosForRegionReturn>(API.GET_PHOTOS_FOR_REGION, { region_id }),
-  addEvent: (data: PostAddEvent) => request.postForm<ResponseType>(API.ADD_EVENT, data)
+  addEvent: (data: PostAddEvent) => request.postForm<ResponseType>(API.ADD_EVENT, data),
+  getEventForEditing: (token: string, event_id: number) =>
+    request.postForm<PostGetEventForEditingReturn>(API.GET_EVENT_FOR_EDITING, { token, event_id }),
+  updateEvent: (data: PostUpdateEvent) => request.postForm<ResponseType>(API.UPDATE_EVENT, data),
+  cancelEvent: (token: string, event_id: number) =>
+    request.postForm<ResponseType>(API.CANCEL_EVENT, { token, event_id })
 };
 };

+ 6 - 2
src/modules/api/events/events-query-keys.tsx

@@ -1,5 +1,5 @@
 export const eventsQueryKeys = {
 export const eventsQueryKeys = {
-  getEventsList: (token: string) => ['getEventsList', token] as const,
+  getEventsList: (token: string, past: number) => ['getEventsList', token, past] as const,
   getEvent: (token: string, url: string) => ['getEvent', { token, url }] as const,
   getEvent: (token: string, url: string) => ['getEvent', { token, url }] as const,
   joinEvent: () => ['joinEvent'] as const,
   joinEvent: () => ['joinEvent'] as const,
   unjoinEvent: () => ['unjoinEvent'] as const,
   unjoinEvent: () => ['unjoinEvent'] as const,
@@ -11,5 +11,9 @@ export const eventsQueryKeys = {
     ['getMorePhotos', { token, event_id, last_id }] as const,
     ['getMorePhotos', { token, event_id, last_id }] as const,
   canAddEvent: (token: string) => ['canAddEvent', token] as const,
   canAddEvent: (token: string) => ['canAddEvent', token] as const,
   getPhotosForRegion: () => ['getPhotosForRegion'] as const,
   getPhotosForRegion: () => ['getPhotosForRegion'] as const,
-  addEvent: () => ['addEvent'] as const
+  getPhotosForRegionQuery: (region_id: number) => ['getPhotosForRegionQuery', region_id] as const,
+  addEvent: () => ['addEvent'] as const,
+  getEventForEditing: () => ['getEventForEditing'] as const,
+  updateEvent: () => ['updateEvent'] as const,
+  cancelEvent: () => ['cancelEvent'] as const,
 };
 };

+ 3 - 0
src/modules/api/events/queries/index.ts

@@ -10,3 +10,6 @@ export * from './use-post-get-more-photos';
 export * from './use-post-can-add-event';
 export * from './use-post-can-add-event';
 export * from './use-post-get-photos-for-region';
 export * from './use-post-get-photos-for-region';
 export * from './use-post-add-event';
 export * from './use-post-add-event';
+export * from './use-post-get-event-for-editing';
+export * from './use-post-update-event';
+export * from './use-post-cancel-event';

+ 22 - 0
src/modules/api/events/queries/use-post-cancel-event.tsx

@@ -0,0 +1,22 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { eventsQueryKeys } from '../events-query-keys';
+import { eventsApi } from '../events-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostCancelEventMutation = () => {
+  return useMutation<
+    ResponseType,
+    BaseAxiosError,
+    { token: string; event_id: number },
+    ResponseType
+  >({
+    mutationKey: eventsQueryKeys.cancelEvent(),
+    mutationFn: async (data) => {
+      const response = await eventsApi.cancelEvent(data.token, data.event_id);
+      return response.data;
+    }
+  });
+};

+ 22 - 0
src/modules/api/events/queries/use-post-get-event-for-editing.tsx

@@ -0,0 +1,22 @@
+import { useQuery } from '@tanstack/react-query';
+import { useMutation } from '@tanstack/react-query';
+
+import { eventsQueryKeys } from '../events-query-keys';
+import { eventsApi, type PostGetEventForEditingReturn } from '../events-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetEventForEditingMutation = () => {
+  return useMutation<
+    PostGetEventForEditingReturn,
+    BaseAxiosError,
+    { token: string; event_id: number },
+    PostGetEventForEditingReturn
+  >({
+    mutationKey: eventsQueryKeys.getEventForEditing(),
+    mutationFn: async (data) => {
+      const response = await eventsApi.getEventForEditing(data.token, data.event_id);
+      return response.data;
+    }
+  });
+};

+ 3 - 3
src/modules/api/events/queries/use-post-get-event-list.tsx

@@ -5,11 +5,11 @@ import { eventsApi, type PostGetEventsListReturn } from '../events-api';
 
 
 import type { BaseAxiosError } from '../../../../types';
 import type { BaseAxiosError } from '../../../../types';
 
 
-export const useGetEventsListQuery = (token: string, enabled: boolean) => {
+export const useGetEventsListQuery = (token: string, past: 0 | 1, enabled: boolean) => {
   return useQuery<PostGetEventsListReturn, BaseAxiosError>({
   return useQuery<PostGetEventsListReturn, BaseAxiosError>({
-    queryKey: eventsQueryKeys.getEventsList(token),
+    queryKey: eventsQueryKeys.getEventsList(token, past),
     queryFn: async () => {
     queryFn: async () => {
-      const response = await eventsApi.getEventsList(token);
+      const response = await eventsApi.getEventsList(token, past);
       return response.data;
       return response.data;
     },
     },
     enabled
     enabled

+ 12 - 0
src/modules/api/events/queries/use-post-get-photos-for-region.tsx

@@ -1,4 +1,5 @@
 import { useMutation } from '@tanstack/react-query';
 import { useMutation } from '@tanstack/react-query';
+import { useQuery } from '@tanstack/react-query';
 
 
 import { eventsQueryKeys } from '../events-query-keys';
 import { eventsQueryKeys } from '../events-query-keys';
 import { type PostGetPhotosForRegionReturn, eventsApi } from '../events-api';
 import { type PostGetPhotosForRegionReturn, eventsApi } from '../events-api';
@@ -19,3 +20,14 @@ export const usePostGetPhotosForRegionMutation = () => {
     }
     }
   });
   });
 };
 };
+
+export const useGetPhotosForRegionQuery = (region_id: number, enabled: boolean) => {
+  return useQuery<PostGetPhotosForRegionReturn, BaseAxiosError>({
+    queryKey: eventsQueryKeys.getPhotosForRegionQuery(region_id),
+    queryFn: async () => {
+      const response = await eventsApi.getPhotosForRegion(region_id);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 17 - 0
src/modules/api/events/queries/use-post-update-event.tsx

@@ -0,0 +1,17 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { eventsQueryKeys } from '../events-query-keys';
+import { type PostUpdateEvent, eventsApi } from '../events-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostUpdateEventMutation = () => {
+  return useMutation<ResponseType, BaseAxiosError, PostUpdateEvent, ResponseType>({
+    mutationKey: eventsQueryKeys.updateEvent(),
+    mutationFn: async (data) => {
+      const response = await eventsApi.updateEvent(data);
+      return response.data;
+    }
+  });
+};

+ 4 - 2
src/screens/InAppScreens/MapScreen/RegionViewScreen/ImageCarousel/index.tsx

@@ -13,12 +13,14 @@ const ImageCarousel = ({
   photos,
   photos,
   activeIndex,
   activeIndex,
   setActiveIndex,
   setActiveIndex,
-  openModal
+  openModal,
+  containerStyles
 }: {
 }: {
   photos: PhotosData[];
   photos: PhotosData[];
   activeIndex: number;
   activeIndex: number;
   setActiveIndex: (index: number) => void;
   setActiveIndex: (index: number) => void;
   openModal: (index: number) => void;
   openModal: (index: number) => void;
+  containerStyles?: any;
 }) => {
 }) => {
   const animationStyle = React.useCallback((value: number) => {
   const animationStyle = React.useCallback((value: number) => {
     'worklet';
     'worklet';
@@ -50,7 +52,7 @@ const ImageCarousel = ({
         loop={false}
         loop={false}
       />
       />
 
 
-      <View style={styles.pagination}>
+      <View style={[styles.pagination, containerStyles && containerStyles]}>
         <PaginationDot
         <PaginationDot
           activeDotColor={Colors.DARK_BLUE}
           activeDotColor={Colors.DARK_BLUE}
           inactiveDotColor={'rgba(15, 63, 79, 0.5)'}
           inactiveDotColor={'rgba(15, 63, 79, 0.5)'}

+ 3 - 0
src/screens/InAppScreens/TravelsScreen/Components/AddMapPinModal/index.tsx

@@ -22,6 +22,9 @@ const AddMapPinModal = () => {
 
 
   const handleSheetOpen = (payload: any) => {
   const handleSheetOpen = (payload: any) => {
     setData(payload);
     setData(payload);
+    if (payload?.pin && payload.pin?.coordinate) {
+      setMarker(payload.pin);
+    }
   };
   };
 
 
   const animateMapToRegion = (latitude: number, longitude: number) => {
   const animateMapToRegion = (latitude: number, longitude: number) => {

+ 222 - 65
src/screens/InAppScreens/TravelsScreen/CreateEvent/index.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useRef, useState } from 'react';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
 import {
 import {
   View,
   View,
   Text,
   Text,
@@ -20,7 +20,7 @@ import ImageView from 'better-react-native-image-viewing';
 import { StoreType, storage } from 'src/storage';
 import { StoreType, storage } from 'src/storage';
 
 
 import AddImgSvg from 'assets/icons/travels-screens/add-img.svg';
 import AddImgSvg from 'assets/icons/travels-screens/add-img.svg';
-import { Button, Header, Input, PageWrapper } from 'src/components';
+import { Button, Header, Input, Loading, PageWrapper, WarningModal } from 'src/components';
 import { Colors } from 'src/theme';
 import { Colors } from 'src/theme';
 
 
 import EarthIcon from 'assets/icons/travels-section/earth.svg';
 import EarthIcon from 'assets/icons/travels-section/earth.svg';
@@ -31,17 +31,24 @@ import CalendarSvg from '../../../../../assets/icons/calendar.svg';
 import RangeCalendar from 'src/components/Calendars/RangeCalendar';
 import RangeCalendar from 'src/components/Calendars/RangeCalendar';
 import LocationIcon from 'assets/icons/bottom-navigation/map.svg';
 import LocationIcon from 'assets/icons/bottom-navigation/map.svg';
 import { ModalFlatList } from 'src/components/FlatList/modal-flatlist';
 import { ModalFlatList } from 'src/components/FlatList/modal-flatlist';
-import { usePostAddEventMutation, usePostGetPhotosForRegionMutation } from '@api/events';
+import {
+  usePostAddEventMutation,
+  usePostCancelEventMutation,
+  usePostGetPhotosForRegionMutation,
+  usePostUpdateEventMutation
+} from '@api/events';
 import { SheetManager } from 'react-native-actions-sheet';
 import { SheetManager } from 'react-native-actions-sheet';
 import PhotosForRegionModal from '../Components/PhotosForRegionModal/PhotosForRegionModal';
 import PhotosForRegionModal from '../Components/PhotosForRegionModal/PhotosForRegionModal';
 import { API_HOST } from 'src/constants';
 import { API_HOST } from 'src/constants';
 import AddMapPinModal from '../Components/AddMapPinModal';
 import AddMapPinModal from '../Components/AddMapPinModal';
 import { InputTimePicker } from 'src/components/Calendar/InputTimePicker';
 import { InputTimePicker } from 'src/components/Calendar/InputTimePicker';
+import { NAVIGATION_PAGES } from 'src/types';
 
 
 const EventSchema = yup.object({
 const EventSchema = yup.object({
   event_name: yup.string().required().min(3),
   event_name: yup.string().required().min(3),
   date: yup.date().nullable().required(),
   date: yup.date().nullable().required(),
-  time: yup.date().nullable().required(),
+  time_from: yup.date().nullable().required(),
+  time_to: yup.date().nullable().required(),
   capacity: yup.number().optional(),
   capacity: yup.number().optional(),
   region: yup.number().required(),
   region: yup.number().required(),
   photo: yup.number().nullable().optional(),
   photo: yup.number().nullable().optional(),
@@ -51,19 +58,69 @@ const EventSchema = yup.object({
   details: yup.string().required()
   details: yup.string().required()
 });
 });
 
 
-const CreateEventScreen = () => {
+const CreateEventScreen = ({ route }: { route: any }) => {
+  const eventId = route.params?.eventId;
+  const eventData = route.params?.event;
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
   const navigation = useNavigation();
   const navigation = useNavigation();
   const scrollRef = useRef<ScrollView>(null);
   const scrollRef = useRef<ScrollView>(null);
   const richText = useRef<RichEditor | null>(null);
   const richText = useRef<RichEditor | null>(null);
   const { mutateAsync: getPhotosForRegion } = usePostGetPhotosForRegionMutation();
   const { mutateAsync: getPhotosForRegion } = usePostGetPhotosForRegionMutation();
   const { mutateAsync: addEvent } = usePostAddEventMutation();
   const { mutateAsync: addEvent } = usePostAddEventMutation();
+  const { mutateAsync: updateEvent } = usePostUpdateEventMutation();
+  const { mutateAsync: cancelEvent } = usePostCancelEventMutation();
 
 
   const [isSubmitting, setIsSubmitting] = useState(false);
   const [isSubmitting, setIsSubmitting] = useState(false);
   const [calendarVisible, setCalendarVisible] = useState(false);
   const [calendarVisible, setCalendarVisible] = useState(false);
   const [isViewerVisible, setIsViewerVisible] = useState(false);
   const [isViewerVisible, setIsViewerVisible] = useState(false);
   const [photos, setPhotos] = useState<any[]>([]);
   const [photos, setPhotos] = useState<any[]>([]);
 
 
+  function timeStringToDate(timeStr: string): Date {
+    const [hours, minutes] = timeStr.split(':').map(Number);
+    const date = new Date();
+
+    date.setHours(hours, minutes, 0, 0);
+    return date;
+  }
+
+  const initialData: any = {
+    event_name: eventData?.title ?? '',
+    date: eventData?.date ?? '',
+    time_from: eventData?.time_from ? timeStringToDate(eventData.time_from) : null,
+    time_to: eventData?.time_to ? timeStringToDate(eventData.time_to) : null,
+    capacity: eventData?.capacity ?? '',
+    region: eventData?.region ?? null,
+    photo: null,
+    city: eventData?.address1 ?? '',
+    address: eventData?.address2 ?? '',
+    pin:
+      eventData && eventData?.lat
+        ? {
+            coordinate: {
+              longitude: eventData?.lon,
+              latitude: eventData?.lat
+            },
+            name: eventData?.address2
+          }
+        : null,
+    details: eventData?.details ?? ''
+  };
+
+  const [modalInfo, setModalInfo] = useState({
+    visible: false,
+    type: 'success',
+    title: '',
+    message: '',
+    buttonTitle: 'OK',
+    action: () => {}
+  });
+
+  useEffect(() => {
+    if (eventData && eventData.region) {
+      handleGetPhotosForRegion(eventData.region);
+    }
+  }, [eventData]);
+
   const handleGetPhotosForRegion = useCallback(
   const handleGetPhotosForRegion = useCallback(
     async (regionId: number) => {
     async (regionId: number) => {
       await getPhotosForRegion(
       await getPhotosForRegion(
@@ -80,6 +137,26 @@ const CreateEventScreen = () => {
     [token]
     [token]
   );
   );
 
 
+  const handleCancelEvent = () => {
+    setModalInfo({
+      visible: true,
+      type: 'delete',
+      title: 'Cancel event',
+      buttonTitle: 'Cancel',
+      message: `Are you sure you want to cancel this event?`,
+      action: () => {
+        cancelEvent(
+          { token, event_id: eventId },
+          {
+            onSuccess: (res) => {
+              navigation.navigate(NAVIGATION_PAGES.EVENTS as never);
+            }
+          }
+        );
+      }
+    });
+  };
+
   return (
   return (
     <PageWrapper>
     <PageWrapper>
       <Header label="Add event" />
       <Header label="Add event" />
@@ -92,18 +169,7 @@ const CreateEventScreen = () => {
           <ScrollView ref={scrollRef} showsVerticalScrollIndicator={false}>
           <ScrollView ref={scrollRef} showsVerticalScrollIndicator={false}>
             <Formik
             <Formik
               validationSchema={EventSchema}
               validationSchema={EventSchema}
-              initialValues={{
-                event_name: '',
-                date: '',
-                time: null,
-                capacity: '',
-                region: null,
-                photo: null,
-                city: '',
-                address: '',
-                pin: null,
-                details: ''
-              }}
+              initialValues={initialData}
               onSubmit={async (values) => {
               onSubmit={async (values) => {
                 setIsSubmitting(true);
                 setIsSubmitting(true);
 
 
@@ -124,27 +190,58 @@ const CreateEventScreen = () => {
 
 
                 if (values.capacity) {
                 if (values.capacity) {
                   newEvent.capacity = Number(values.capacity);
                   newEvent.capacity = Number(values.capacity);
+                } else {
+                  newEvent.capacity = 0;
+                }
+
+                if (values.time_from) {
+                  newEvent.time_from = (values.time_from as Date).toLocaleTimeString([], {
+                    hour: '2-digit',
+                    minute: '2-digit'
+                  });
                 }
                 }
 
 
-                if (values.time) {
-                  newEvent.time = (values.time as Date).toLocaleTimeString([], {
+                if (values.time_to) {
+                  newEvent.time_to = (values.time_to as Date).toLocaleTimeString([], {
                     hour: '2-digit',
                     hour: '2-digit',
                     minute: '2-digit'
                     minute: '2-digit'
                   });
                   });
                 }
                 }
 
 
-                await addEvent(
-                  { token, event: JSON.stringify(newEvent) },
-                  {
-                    onSuccess: (res) => {
-                      setIsSubmitting(false);
-                      navigation.goBack();
-                    },
-                    onError: (err) => {
-                      setIsSubmitting(false);
+                if (eventId) {
+                  await updateEvent(
+                    { token, event_id: eventId, event: JSON.stringify(newEvent) },
+                    {
+                      onSuccess: (res) => {
+                        setIsSubmitting(false);
+                        navigation.goBack();
+                      },
+                      onError: (err) => {
+                        setIsSubmitting(false);
+                      }
+                    }
+                  );
+                } else {
+                  await addEvent(
+                    { token, event: JSON.stringify(newEvent) },
+                    {
+                      onSuccess: (res) => {
+                        setIsSubmitting(false);
+                        setModalInfo({
+                          visible: true,
+                          type: 'success',
+                          title: 'Success',
+                          buttonTitle: 'OK',
+                          message: `Thank you for adding this new meeting. It will undergo review soon. You'll be notified via email once the meeting is approved.`,
+                          action: () => {}
+                        });
+                      },
+                      onError: (err) => {
+                        setIsSubmitting(false);
+                      }
                     }
                     }
-                  }
-                );
+                  );
+                }
               }}
               }}
             >
             >
               {(props) => (
               {(props) => (
@@ -171,12 +268,25 @@ const CreateEventScreen = () => {
                     icon={<CalendarSvg fill={Colors.LIGHT_GRAY} width={20} height={20} />}
                     icon={<CalendarSvg fill={Colors.LIGHT_GRAY} width={20} height={20} />}
                   />
                   />
 
 
-                  <InputTimePicker
-                    headerTitle={'Select Time'}
-                    defaultTime={props.values.time}
-                    selectedTime={(time) => props.setFieldValue('time', time)}
-                    formikError={props.touched.time && props.errors.time}
-                  />
+                  <View style={{ flexDirection: 'row', gap: 8 }}>
+                    <InputTimePicker
+                      headerTitle={'Select Start Time'}
+                      defaultTime={props.values.time_from}
+                      selectedTime={(time) => props.setFieldValue('time_from', time)}
+                      formikError={props.touched.time_from && props.errors.time_from}
+                      inputHeader={'Start time'}
+                      placeholder="Choose a time"
+                    />
+
+                    <InputTimePicker
+                      headerTitle={'Select End Time'}
+                      defaultTime={props.values.time_to}
+                      selectedTime={(time) => props.setFieldValue('time_to', time)}
+                      formikError={props.touched.time_to && props.errors.time_to}
+                      inputHeader={'End time'}
+                      placeholder="Choose a time"
+                    />
+                  </View>
 
 
                   <Input
                   <Input
                     header={'Maximum capacity'}
                     header={'Maximum capacity'}
@@ -189,18 +299,27 @@ const CreateEventScreen = () => {
                     icon={<NomadsIcon fill={Colors.LIGHT_GRAY} width={20} height={20} />}
                     icon={<NomadsIcon fill={Colors.LIGHT_GRAY} width={20} height={20} />}
                   />
                   />
 
 
-                  <ModalFlatList
-                    headerTitle={'NomadMania region'}
-                    selectedObject={(data) => {
-                      props.setFieldValue('region', data.id);
-                      props.setFieldValue('photo', null);
-                      handleGetPhotosForRegion(data.id);
-                    }}
-                    placeholder="Please choose a region"
-                    formikError={
-                      props.touched.region && !props.values.region ? props.errors.region : null
-                    }
-                  />
+                  {eventId ? (
+                    <Input
+                      header={'NomadMania region'}
+                      inputMode={'none'}
+                      editable={false}
+                      value={eventData?.region_name}
+                    />
+                  ) : (
+                    <ModalFlatList
+                      headerTitle={'NomadMania region'}
+                      selectedObject={(data) => {
+                        props.setFieldValue('region', data.id);
+                        props.setFieldValue('photo', null);
+                        handleGetPhotosForRegion(data.id);
+                      }}
+                      placeholder="Please choose a region"
+                      formikError={
+                        props.touched.region && !props.values.region ? props.errors.region : null
+                      }
+                    />
+                  )}
 
 
                   {props.values.region && photos.length > 0 ? (
                   {props.values.region && photos.length > 0 ? (
                     <Input
                     <Input
@@ -279,7 +398,8 @@ const CreateEventScreen = () => {
                           setPin: (pin: any) => {
                           setPin: (pin: any) => {
                             props.setFieldValue('pin', pin);
                             props.setFieldValue('pin', pin);
                             props.setFieldValue('city', pin?.city);
                             props.setFieldValue('city', pin?.city);
-                          }
+                          },
+                          pin: props.values.pin
                         } as any
                         } as any
                       })
                       })
                     }
                     }
@@ -388,23 +508,44 @@ const CreateEventScreen = () => {
                     ) : null}
                     ) : null}
                   </View>
                   </View>
 
 
-                  <View style={{ marginTop: 15, marginBottom: 15, gap: 8 }}>
-                    <Button onPress={() => props.handleSubmit()} disabled={isSubmitting}>
-                      Save
-                    </Button>
+                  {eventId ? (
+                    <View style={{ marginTop: 15, marginBottom: 15, gap: 8 }}>
+                      <Button onPress={() => props.handleSubmit()} disabled={isSubmitting}>
+                        Update event
+                      </Button>
+
+                      <Button
+                        variant={ButtonVariants.OPACITY}
+                        containerStyles={{
+                          backgroundColor: Colors.RED,
+                          borderColor: Colors.RED
+                        }}
+                        textStyles={{ color: Colors.WHITE }}
+                        onPress={handleCancelEvent}
+                      >
+                        Cancel event
+                      </Button>
+                    </View>
+                  ) : (
+                    <View style={{ marginTop: 15, marginBottom: 15, gap: 8 }}>
+                      <Button onPress={() => props.handleSubmit()} disabled={isSubmitting}>
+                        Save
+                      </Button>
+
+                      <Button
+                        variant={ButtonVariants.OPACITY}
+                        containerStyles={{
+                          backgroundColor: Colors.WHITE,
+                          borderColor: Colors.BORDER_LIGHT
+                        }}
+                        textStyles={{ color: Colors.DARK_BLUE }}
+                        onPress={() => navigation.goBack()}
+                      >
+                        Cancel
+                      </Button>
+                    </View>
+                  )}
 
 
-                    <Button
-                      variant={ButtonVariants.OPACITY}
-                      containerStyles={{
-                        backgroundColor: Colors.WHITE,
-                        borderColor: Colors.BORDER_LIGHT
-                      }}
-                      textStyles={{ color: Colors.DARK_BLUE }}
-                      onPress={() => navigation.goBack()}
-                    >
-                      Cancel
-                    </Button>
-                  </View>
                   <RangeCalendar
                   <RangeCalendar
                     isModalVisible={calendarVisible}
                     isModalVisible={calendarVisible}
                     closeModal={(startDate?: string | null, endDate?: string | null) => {
                     closeModal={(startDate?: string | null, endDate?: string | null) => {
@@ -435,6 +576,22 @@ const CreateEventScreen = () => {
       </KeyboardAvoidingView>
       </KeyboardAvoidingView>
       <PhotosForRegionModal />
       <PhotosForRegionModal />
       <AddMapPinModal />
       <AddMapPinModal />
+      <WarningModal
+        type={modalInfo.type}
+        isVisible={modalInfo.visible}
+        buttonTitle={modalInfo.buttonTitle}
+        message={modalInfo.message}
+        action={modalInfo.action}
+        onClose={() => {
+          if (modalInfo.type === 'success') {
+            navigation.goBack();
+            setModalInfo({ ...modalInfo, visible: false });
+          } else {
+            setModalInfo({ ...modalInfo, visible: false });
+          }
+        }}
+        title={modalInfo.title}
+      />
     </PageWrapper>
     </PageWrapper>
   );
   );
 };
 };

+ 121 - 37
src/screens/InAppScreens/TravelsScreen/EventScreen/index.tsx

@@ -24,6 +24,7 @@ import { API_HOST, APP_VERSION } from 'src/constants';
 import { StoreType, storage } from 'src/storage';
 import { StoreType, storage } from 'src/storage';
 import { MaterialCommunityIcons } from '@expo/vector-icons';
 import { MaterialCommunityIcons } from '@expo/vector-icons';
 import * as Progress from 'react-native-progress';
 import * as Progress from 'react-native-progress';
+import ImageView from 'better-react-native-image-viewing';
 
 
 import ChevronLeft from 'assets/icons/chevron-left.svg';
 import ChevronLeft from 'assets/icons/chevron-left.svg';
 import MapSvg from 'assets/icons/travels-screens/map-location.svg';
 import MapSvg from 'assets/icons/travels-screens/map-location.svg';
@@ -43,9 +44,12 @@ import {
   EventAttachments,
   EventAttachments,
   EventData,
   EventData,
   EventPhotos,
   EventPhotos,
+  useGetEventForEditingMutation,
   useGetEventQuery,
   useGetEventQuery,
+  useGetPhotosForRegionQuery,
   usePostDeleteFileMutation,
   usePostDeleteFileMutation,
   usePostEventAddFileMutation,
   usePostEventAddFileMutation,
+  usePostGetPhotosForRegionMutation,
   usePostJoinEventMutation,
   usePostJoinEventMutation,
   usePostUnjoinEventMutation,
   usePostUnjoinEventMutation,
   usePostUploadPhotoMutation,
   usePostUploadPhotoMutation,
@@ -65,6 +69,9 @@ import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view
 import Tooltip from 'react-native-walkthrough-tooltip';
 import Tooltip from 'react-native-walkthrough-tooltip';
 import WebView from 'react-native-webview';
 import WebView from 'react-native-webview';
 import ClockIcon from 'assets/icons/events/clock.svg';
 import ClockIcon from 'assets/icons/events/clock.svg';
+import { PhotosData } from '../../MapScreen/RegionViewScreen/types';
+import ImageCarousel from '../../MapScreen/RegionViewScreen/ImageCarousel';
+import EditSvg from 'assets/icons/events/edit.svg';
 
 
 type TempFile = {
 type TempFile = {
   filetype: string;
   filetype: string;
@@ -80,7 +87,7 @@ const fileWidth = Dimensions.get('window').width / 5;
 const EventScreen = ({ route }: { route: any }) => {
 const EventScreen = ({ route }: { route: any }) => {
   const eventUrl = route.params?.url;
   const eventUrl = route.params?.url;
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
-  const currentUserId = (storage.get('uid', StoreType.NUMBER) as number) ?? 0;
+  const currentUserId = (storage.get('uid', StoreType.STRING) as string) ?? 0;
   const navigation = useNavigation();
   const navigation = useNavigation();
   const { width: windowWidth } = useWindowDimensions();
   const { width: windowWidth } = useWindowDimensions();
   const contentWidth = windowWidth * 0.9;
   const contentWidth = windowWidth * 0.9;
@@ -93,6 +100,7 @@ const EventScreen = ({ route }: { route: any }) => {
   const { mutateAsync: saveFile } = usePostEventAddFileMutation();
   const { mutateAsync: saveFile } = usePostEventAddFileMutation();
   const { mutateAsync: deleteFile } = usePostDeleteFileMutation();
   const { mutateAsync: deleteFile } = usePostDeleteFileMutation();
   const { mutateAsync: uploadPhoto } = usePostUploadPhotoMutation();
   const { mutateAsync: uploadPhoto } = usePostUploadPhotoMutation();
+  const { mutateAsync: getForEditing } = useGetEventForEditingMutation();
 
 
   const [isExpanded, setIsExpanded] = useState(false);
   const [isExpanded, setIsExpanded] = useState(false);
   const [tooltipUser, setTooltipUser] = useState<number | null>(null);
   const [tooltipUser, setTooltipUser] = useState<number | null>(null);
@@ -113,6 +121,13 @@ const EventScreen = ({ route }: { route: any }) => {
   const [myFiles, setMyFiles] = useState<EventAttachments[]>([]);
   const [myFiles, setMyFiles] = useState<EventAttachments[]>([]);
   const [photos, setPhotos] = useState<(EventPhotos & { isSending?: boolean })[]>([]);
   const [photos, setPhotos] = useState<(EventPhotos & { isSending?: boolean })[]>([]);
   const [isUploading, setIsUploading] = useState(false);
   const [isUploading, setIsUploading] = useState(false);
+  const [photosForRegion, setPhotosForRegion] = useState<{ uriSmall: string; uri: string }[]>([]);
+  const [activeIndex, setActiveIndex] = useState(0);
+  const [isImageModalVisible, setIsImageModalVisible] = useState(false);
+  const [currentImageIndex, setCurrentImageIndex] = useState(0);
+  const [nmId, setNmId] = useState<number | null>(null);
+
+  const { data: photosData } = useGetPhotosForRegionQuery(nmId ?? 0, nmId !== null);
 
 
   const [modalInfo, setModalInfo] = useState({
   const [modalInfo, setModalInfo] = useState({
     visible: false,
     visible: false,
@@ -123,10 +138,21 @@ const EventScreen = ({ route }: { route: any }) => {
     action: () => {}
     action: () => {}
   });
   });
 
 
+  useEffect(() => {
+    photosData &&
+      setPhotosForRegion(
+        photosData?.photos?.map((item) => ({
+          uriSmall: `${API_HOST}/ajax/pic/${item}/small`,
+          uri: `${API_HOST}/ajax/pic/${item}/full`
+        })) ?? []
+      );
+  }, [photosData]);
+
   useEffect(() => {
   useEffect(() => {
     if (data && data.data) {
     if (data && data.data) {
       setEvent(data.data);
       setEvent(data.data);
       setJoined(data.data.joined);
       setJoined(data.data.joined);
+      setNmId(data.data.settings.nm_region ?? null);
 
 
       setMyFiles(data.data.files ?? []);
       setMyFiles(data.data.files ?? []);
       setPhotos(data.data.photos);
       setPhotos(data.data.photos);
@@ -164,6 +190,11 @@ const EventScreen = ({ route }: { route: any }) => {
     }, [navigation])
     }, [navigation])
   );
   );
 
 
+  const openModal = (index: number) => {
+    setCurrentImageIndex(index);
+    setIsImageModalVisible(true);
+  };
+
   const handlePreviewDocument = useCallback(async (url: string, fileName: string) => {
   const handlePreviewDocument = useCallback(async (url: string, fileName: string) => {
     try {
     try {
       const dirExist = await FileSystem.getInfoAsync(CACHED_ATTACHMENTS_DIR);
       const dirExist = await FileSystem.getInfoAsync(CACHED_ATTACHMENTS_DIR);
@@ -357,7 +388,7 @@ const EventScreen = ({ route }: { route: any }) => {
         type: 'success',
         type: 'success',
         title: 'Success',
         title: 'Success',
         buttonTitle: 'OK',
         buttonTitle: 'OK',
-        message: `Thank you for joing, we’ll get back to you soon.`,
+        message: `Thank you for joining, we’ll get back to you soon.`,
         action: () => {}
         action: () => {}
       });
       });
     }
     }
@@ -549,7 +580,7 @@ const EventScreen = ({ route }: { route: any }) => {
   };
   };
 
 
   const formatEventDate = (event: EventData) => {
   const formatEventDate = (event: EventData) => {
-    if (event.settings.date_from && event.settings.date_to) {
+    if (event.date_from && event.date_to) {
       return (
       return (
         <View>
         <View>
           <Text
           <Text
@@ -575,7 +606,7 @@ const EventScreen = ({ route }: { route: any }) => {
         </View>
         </View>
       );
       );
     } else {
     } else {
-      let date = moment(event.settings.date, 'YYYY-MM-DD').format('DD MMMM YYYY');
+      let date = moment(event.date, 'YYYY-MM-DD').format('DD MMMM YYYY');
 
 
       return (
       return (
         <View>
         <View>
@@ -588,7 +619,20 @@ const EventScreen = ({ route }: { route: any }) => {
           >
           >
             {date}
             {date}
           </Text>
           </Text>
-          {event.time && (
+          {event.time_from && event.time_to ? (
+            <View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
+              <ClockIcon fill={Colors.DARK_BLUE} height={12} width={12} />
+              <Text
+                style={{
+                  fontSize: getFontSize(12),
+                  fontWeight: '600',
+                  color: Colors.DARK_BLUE
+                }}
+              >
+                {event.time_from} - {event.time_to}
+              </Text>
+            </View>
+          ) : event.time ? (
             <View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
             <View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
               <ClockIcon fill={Colors.DARK_BLUE} height={12} width={12} />
               <ClockIcon fill={Colors.DARK_BLUE} height={12} width={12} />
               <Text
               <Text
@@ -601,7 +645,7 @@ const EventScreen = ({ route }: { route: any }) => {
                 {event.time}
                 {event.time}
               </Text>
               </Text>
             </View>
             </View>
-          )}
+          ) : null}
         </View>
         </View>
       );
       );
     }
     }
@@ -710,35 +754,17 @@ const EventScreen = ({ route }: { route: any }) => {
           showsVerticalScrollIndicator={false}
           showsVerticalScrollIndicator={false}
           removeClippedSubviews={false}
           removeClippedSubviews={false}
         >
         >
-          <Image source={{ uri: photoUrl }} style={{ width: '100%', height: 220 }} />
-
-          {/* <TouchableOpacity
-            onPress={() => {
-              //     navigation.dispatch(
-              //       CommonActions.reset({
-              //         index: 1,
-              //         routes: [
-              //           {
-              //             name: NAVIGATION_PAGES.IN_APP_MAP_TAB,
-              //             state: {
-              //               routes: [
-              //                 {
-              //                   name: NAVIGATION_PAGES.MAP_TAB,
-              //                   params: { id: regionId, type: type === 'nm' ? 'regions' : 'places' }
-              //                 }
-              //               ]
-              //             }
-              //           }
-              //         ]
-              //       })
-              //     )
-            }}
-            style={styles.goToMapBtn}
-          >
-            <View style={styles.chevronWrapper}>
-              <MapSvg fill={Colors.WHITE} />
-            </View>
-          </TouchableOpacity> */}
+          {event.settings.type === 1 && photosForRegion.length > 0 ? (
+            <ImageCarousel
+              photos={photosForRegion as PhotosData[]}
+              activeIndex={activeIndex}
+              setActiveIndex={setActiveIndex}
+              openModal={openModal}
+              containerStyles={{ marginBottom: 0 }}
+            />
+          ) : (
+            <Image source={{ uri: photoUrl }} style={{ width: '100%', height: 220 }} />
+          )}
 
 
           {registrationInfo && (
           {registrationInfo && (
             <View
             <View
@@ -985,7 +1011,57 @@ const EventScreen = ({ route }: { route: any }) => {
               )}
               )}
             </View>
             </View>
 
 
-            {joined ? (
+            {/* TO DO */}
+            {event.settings.host_profile === +currentUserId &&
+            event.settings.type === 1 &&
+            !event.archived ? (
+              <TouchableOpacity
+                style={{
+                  flexDirection: 'row',
+                  alignItems: 'center',
+                  justifyContent: 'center',
+                  paddingVertical: 8,
+                  paddingHorizontal: 12,
+                  borderRadius: 20,
+                  backgroundColor: Colors.ORANGE,
+                  gap: 6,
+                  borderWidth: 1,
+                  borderColor: Colors.ORANGE
+                }}
+                onPress={() =>
+                  getForEditing(
+                    { token, event_id: event.id },
+                    {
+                      onSuccess: (res) => {
+                        navigation.navigate(
+                          ...([
+                            NAVIGATION_PAGES.CREATE_EVENT,
+                            {
+                              eventId: event.id,
+                              event: res
+                            }
+                          ] as never)
+                        );
+                      }
+                    }
+                  )
+                }
+              >
+                <EditSvg fill={Colors.WHITE} width={16} height={16} />
+                <Text
+                  style={{
+                    color: Colors.WHITE,
+                    fontSize: getFontSize(14),
+                    fontFamily: 'montserrat-700',
+                    textTransform: 'uppercase'
+                  }}
+                >
+                  Edit
+                </Text>
+              </TouchableOpacity>
+            ) : null}
+            {event.settings.host_profile === +currentUserId ||
+            event.archived === 1 ? null : joined ? (
               <TouchableOpacity
               <TouchableOpacity
                 style={{
                 style={{
                   flexDirection: 'row',
                   flexDirection: 'row',
@@ -1348,6 +1424,14 @@ const EventScreen = ({ route }: { route: any }) => {
         onClose={() => setModalInfo({ ...modalInfo, visible: false })}
         onClose={() => setModalInfo({ ...modalInfo, visible: false })}
         title={modalInfo.title}
         title={modalInfo.title}
       />
       />
+      <ImageView
+        images={photosForRegion}
+        imageIndex={currentImageIndex}
+        visible={isImageModalVisible}
+        onRequestClose={() => setIsImageModalVisible(false)}
+        backgroundColor={Colors.DARK_BLUE}
+        onImageIndexChange={setActiveIndex}
+      />
     </View>
     </View>
   );
   );
 };
 };
@@ -1365,7 +1449,7 @@ const WebDisplay = React.memo(function WebDisplay({ html }: { html: string }) {
   const processedHtml = React.useMemo(() => {
   const processedHtml = React.useMemo(() => {
     let updatedHtml = html;
     let updatedHtml = html;
     const hrefRegex = /href="((?!http)[^"]+)"/g;
     const hrefRegex = /href="((?!http)[^"]+)"/g;
-    const imgSrcRegex = /src="((?:\.{0,2}\/)*img\/[^"]*)"/g;
+    const imgSrcRegex = /src="((?:\.{0,2}\/)*[^":]+)"/g;
 
 
     const normalizePath = (path: string): string => {
     const normalizePath = (path: string): string => {
       const segments = path.split('/').filter(Boolean);
       const segments = path.split('/').filter(Boolean);

+ 110 - 35
src/screens/InAppScreens/TravelsScreen/EventsScreen/index.tsx

@@ -1,5 +1,13 @@
-import React, { useEffect, useState } from 'react';
-import { View, Text, Image, TouchableOpacity } from 'react-native';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import {
+  View,
+  Text,
+  Image,
+  TouchableOpacity,
+  ScrollView,
+  LayoutAnimation,
+  findNodeHandle
+} from 'react-native';
 import { FlashList } from '@shopify/flash-list';
 import { FlashList } from '@shopify/flash-list';
 import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
 import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
 import { styles } from './styles';
 import { styles } from './styles';
@@ -21,16 +29,40 @@ import moment from 'moment';
 import { API_HOST } from 'src/constants';
 import { API_HOST } from 'src/constants';
 import { Grayscale } from 'react-native-color-matrix-image-filters';
 import { Grayscale } from 'react-native-color-matrix-image-filters';
 import { renderSpotsText } from './utils';
 import { renderSpotsText } from './utils';
-import ClockIcon from 'assets/icons/events/clock.svg';
+import ChevronIcon from 'assets/icons/chevron-left.svg';
 
 
 const EventsScreen = () => {
 const EventsScreen = () => {
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
   const token = (storage.get('token', StoreType.STRING) as string) ?? null;
-  const { data, refetch } = useGetEventsListQuery(token, true);
+  const { data, refetch } = useGetEventsListQuery(token, 0, true);
+  const { data: pastData } = useGetEventsListQuery(token, 1, true);
   const { data: canAddEvent } = useGetCanAddEventQuery(token, true);
   const { data: canAddEvent } = useGetCanAddEventQuery(token, true);
   const navigation = useNavigation();
   const navigation = useNavigation();
   const [searchQuery, setSearchQuery] = useState('');
   const [searchQuery, setSearchQuery] = useState('');
   const [events, setEvents] = useState<SingleEvent[]>([]);
   const [events, setEvents] = useState<SingleEvent[]>([]);
+  const [pastEvents, setPastEvents] = useState<SingleEvent[]>([]);
   const [filteredEvents, setFilteredEvents] = useState<SingleEvent[]>([]);
   const [filteredEvents, setFilteredEvents] = useState<SingleEvent[]>([]);
+  const [filteredPastEvents, setFilteredPastEvents] = useState<SingleEvent[]>([]);
+  const date = new Date();
+
+  const [isExpanded, setIsExpanded] = useState(false);
+  const scrollViewRef = useRef<ScrollView>(null);
+  const sectionRef = useRef<View>(null);
+
+  const toggleExpand = () => {
+    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut, () => {
+      if (!isExpanded && sectionRef.current && scrollViewRef.current) {
+        sectionRef.current.measureLayout(
+          findNodeHandle(scrollViewRef.current)!,
+          (x, y) => {
+            scrollViewRef.current?.scrollTo({ y, animated: true });
+          },
+          () => console.warn('events measureLayout error')
+        );
+      }
+    });
+
+    setIsExpanded(!isExpanded);
+  };
 
 
   useEffect(() => {
   useEffect(() => {
     if (data && data.data) {
     if (data && data.data) {
@@ -39,9 +71,18 @@ const EventsScreen = () => {
     }
     }
   }, [data]);
   }, [data]);
 
 
-  useFocusEffect(() => {
-    refetch();
-  });
+  useEffect(() => {
+    if (pastData && pastData.data) {
+      setPastEvents(pastData.data);
+      setFilteredPastEvents(pastData.data);
+    }
+  }, [pastData]);
+
+  useFocusEffect(
+    useCallback(() => {
+      refetch();
+    }, [navigation])
+  );
 
 
   const handleSearch = (text: string) => {
   const handleSearch = (text: string) => {
     if (text) {
     if (text) {
@@ -52,9 +93,19 @@ const EventsScreen = () => {
           return itemData.indexOf(textData) > -1;
           return itemData.indexOf(textData) > -1;
         }) ?? [];
         }) ?? [];
       setFilteredEvents(searchData);
       setFilteredEvents(searchData);
+
+      const searchPastData =
+        pastEvents.filter((item: any) => {
+          const itemData = item.name ? item.name.toLowerCase() : ''.toLowerCase();
+          const textData = text.toLowerCase();
+          return itemData.indexOf(textData) > -1;
+        }) ?? [];
+      setFilteredPastEvents(searchPastData);
+
       setSearchQuery(text);
       setSearchQuery(text);
     } else {
     } else {
       setFilteredEvents(events);
       setFilteredEvents(events);
+      setFilteredPastEvents(pastEvents);
       setSearchQuery(text);
       setSearchQuery(text);
     }
     }
   };
   };
@@ -85,7 +136,7 @@ const EventsScreen = () => {
     }
     }
 
 
     const photo = item.photo
     const photo = item.photo
-      ? API_HOST + '/webapi/events/get-square-photo/' + item.id
+      ? API_HOST + '/webapi/events/get-square-photo/' + item.id + '?cacheBust=' + date
       : API_HOST + staticImgUrl;
       : API_HOST + staticImgUrl;
 
 
     return (
     return (
@@ -95,7 +146,7 @@ const EventsScreen = () => {
             styles.card,
             styles.card,
             item.type === 2 || item.type === 3 || item.full
             item.type === 2 || item.type === 3 || item.full
               ? { backgroundColor: Colors.FILL_LIGHT }
               ? { backgroundColor: Colors.FILL_LIGHT }
-              : {}
+              : { backgroundColor: Colors.WHITE }
           ]}
           ]}
           onPress={() =>
           onPress={() =>
             navigation.navigate(...([NAVIGATION_PAGES.EVENT, { url: item.url }] as never))
             navigation.navigate(...([NAVIGATION_PAGES.EVENT, { url: item.url }] as never))
@@ -132,14 +183,6 @@ const EventsScreen = () => {
                   {formatEventDate(item)}
                   {formatEventDate(item)}
                 </Text>
                 </Text>
               </View>
               </View>
-              {item.time && (
-                <View style={styles.row}>
-                  <ClockIcon fill={Colors.DARK_BLUE} height={14} width={14} />
-                  <Text style={[styles.dateAndLocation, { flex: 0 }]} numberOfLines={1}>
-                    {item.time}
-                  </Text>
-                </View>
-              )}
             </View>
             </View>
 
 
             <View style={styles.row}>
             <View style={styles.row}>
@@ -192,25 +235,57 @@ const EventsScreen = () => {
         }
         }
       />
       />
 
 
-      <View style={styles.searchContainer}>
-        <Input
-          inputMode={'search'}
-          placeholder={'Search'}
-          onChange={(text) => handleSearch(text)}
-          value={searchQuery}
-          icon={<SearchIcon fill={'#C8C8C8'} width={14} height={14} />}
-          height={38}
+      <ScrollView ref={scrollViewRef} nestedScrollEnabled showsVerticalScrollIndicator={false}>
+        <View style={styles.searchContainer}>
+          <Input
+            inputMode={'search'}
+            placeholder={'Search'}
+            onChange={(text) => handleSearch(text)}
+            value={searchQuery}
+            icon={<SearchIcon fill={'#C8C8C8'} width={14} height={14} />}
+            height={38}
+          />
+        </View>
+
+        <FlashList
+          data={filteredEvents}
+          scrollEnabled={false}
+          keyExtractor={(item) => item.id.toString()}
+          renderItem={renderEventCard}
+          estimatedItemSize={100}
+          contentContainerStyle={styles.listContainer}
+          showsVerticalScrollIndicator={false}
         />
         />
-      </View>
-
-      <FlashList
-        data={filteredEvents}
-        keyExtractor={(item) => item.id.toString()}
-        renderItem={renderEventCard}
-        estimatedItemSize={100}
-        contentContainerStyle={styles.listContainer}
-        showsVerticalScrollIndicator={false}
-      />
+
+        {filteredPastEvents && filteredPastEvents.length ? (
+          <View ref={sectionRef} style={styles.sectionContainer}>
+            <TouchableOpacity onPress={toggleExpand} style={styles.header}>
+              <View style={styles.headerContainer}>
+                <Text style={styles.headerText}>Past Events</Text>
+              </View>
+
+              <View style={styles.chevronContainer}>
+                <ChevronIcon
+                  fill={Colors.DARK_BLUE}
+                  style={[styles.headerIcon, isExpanded ? styles.rotate : null]}
+                />
+              </View>
+            </TouchableOpacity>
+
+            {isExpanded ? (
+              <FlashList
+                data={filteredPastEvents}
+                scrollEnabled={false}
+                keyExtractor={(item) => item.id.toString()}
+                renderItem={renderEventCard}
+                estimatedItemSize={100}
+                contentContainerStyle={styles.listContainer}
+                showsVerticalScrollIndicator={false}
+              />
+            ) : null}
+          </View>
+        ) : null}
+      </ScrollView>
     </PageWrapper>
     </PageWrapper>
   );
   );
 };
 };

+ 45 - 1
src/screens/InAppScreens/TravelsScreen/EventsScreen/styles.tsx

@@ -100,5 +100,49 @@ export const styles = StyleSheet.create({
     fontFamily: 'montserrat-700',
     fontFamily: 'montserrat-700',
     textAlign: 'center'
     textAlign: 'center'
   },
   },
-  row: { flexDirection: 'row', gap: 6, alignItems: 'center' }
+  row: { flexDirection: 'row', gap: 6, alignItems: 'center' },
+  sectionContainer: {
+    marginTop: 12,
+    marginBottom: 12,
+    backgroundColor: '#f9f9f9',
+    borderRadius: 8,
+    paddingHorizontal: 8
+  },
+  headerContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    flex: 1
+  },
+  chevronContainer: {
+    width: 18,
+    height: 18,
+    alignItems: 'center'
+  },
+  itemContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    marginBottom: 16,
+    justifyContent: 'space-between',
+    flex: 1
+  },
+  header: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    paddingVertical: 12,
+    paddingHorizontal: 4,
+    justifyContent: 'space-between',
+    flex: 1
+  },
+  headerText: {
+    fontSize: 14,
+    fontWeight: 'bold',
+    color: Colors.DARK_BLUE,
+    flexShrink: 1
+  },
+  headerIcon: {
+    transform: [{ rotate: '-90deg' }]
+  },
+  rotate: {
+    transform: [{ rotate: '90deg' }]
+  }
 });
 });

+ 8 - 2
src/types/api.ts

@@ -200,7 +200,10 @@ export enum API_ENDPOINT {
   GET_PHOTOS_FOR_REGION = 'get-photos-for-region',
   GET_PHOTOS_FOR_REGION = 'get-photos-for-region',
   ADD_EVENT = 'add-event',
   ADD_EVENT = 'add-event',
   SET_LOCATION_REGIONS = 'set-settings-regions',
   SET_LOCATION_REGIONS = 'set-settings-regions',
-  GET_MASTER = 'get-master'
+  GET_MASTER = 'get-master',
+  GET_EVENT_FOR_EDITING = 'get-event-for-editing',
+  UPDATE_EVENT = 'update-event',
+  CANCEL_EVENT = 'cancel-event'
 }
 }
 
 
 export enum API {
 export enum API {
@@ -373,7 +376,10 @@ export enum API {
   GET_PHOTOS_FOR_REGION = `${API_ROUTE.EVENTS}/${API_ENDPOINT.GET_PHOTOS_FOR_REGION}`,
   GET_PHOTOS_FOR_REGION = `${API_ROUTE.EVENTS}/${API_ENDPOINT.GET_PHOTOS_FOR_REGION}`,
   ADD_EVENT = `${API_ROUTE.EVENTS}/${API_ENDPOINT.ADD_EVENT}`,
   ADD_EVENT = `${API_ROUTE.EVENTS}/${API_ENDPOINT.ADD_EVENT}`,
   SET_LOCATION_REGIONS = `${API_ROUTE.LOCATION}/${API_ENDPOINT.SET_LOCATION_REGIONS}`,
   SET_LOCATION_REGIONS = `${API_ROUTE.LOCATION}/${API_ENDPOINT.SET_LOCATION_REGIONS}`,
-  GET_MASTER = `${API_ROUTE.RANKING}/${API_ENDPOINT.GET_MASTER}`
+  GET_MASTER = `${API_ROUTE.RANKING}/${API_ENDPOINT.GET_MASTER}`,
+  GET_EVENT_FOR_EDITING = `${API_ROUTE.EVENTS}/${API_ENDPOINT.GET_EVENT_FOR_EDITING}`,
+  UPDATE_EVENT = `${API_ROUTE.EVENTS}/${API_ENDPOINT.UPDATE_EVENT}`,
+  CANCEL_EVENT = `${API_ROUTE.EVENTS}/${API_ENDPOINT.CANCEL_EVENT}`
 }
 }
 
 
 export type BaseAxiosError = AxiosError;
 export type BaseAxiosError = AxiosError;