setOpenProfile(!OpenProfile)}
+ />
+
+
+
+
+
+
+ {user?.firstName} {user?.lastName}
+
+
+
+
+
+ {/*
*/}
+
+
+
+ >
+ );
+};
+
+export default ProfileDropDown;
diff --git a/v2/src/components/Forms/Login.tsx b/v2/src/components/Forms/Login.tsx
index c48e0b5..6392be7 100644
--- a/v2/src/components/Forms/Login.tsx
+++ b/v2/src/components/Forms/Login.tsx
@@ -44,7 +44,6 @@ const Login = () => {
setError(data?.error);
if (data?.success) {
console.log('User came from signIn');
- localStorage.setItem('authenticated', 'true');
setTimeout(() => {
setSuccess('Redirecting....');
}, 1000);
diff --git a/v2/src/components/Header/NavBarAuthenticated.tsx b/v2/src/components/Header/NavBarAuthenticated.tsx
index aa30d80..0196d0a 100644
--- a/v2/src/components/Header/NavBarAuthenticated.tsx
+++ b/v2/src/components/Header/NavBarAuthenticated.tsx
@@ -1,7 +1,75 @@
+'use client';
+
import React from 'react';
+import Image from 'next/image';
+import Link from 'next/link';
+import { Add, Notification, CloseSquare, HambergerMenu } from 'iconsax-react';
+import { useRouter } from 'next/navigation';
+import { useUserCtx } from '@/context/UserCtx';
+import { useStateCtx } from '@/context/StateCtx';
+import { cn } from '@/utils';
+import ProfileDropDown from '../DropDowns/ProfileDropDown';
const NavBarAuthenticated = () => {
- return
NavBarAuthenticated
;
+ const { user } = useUserCtx();
+ const { OpenNotification, setOpenNotification, OpenProfile, setOpenProfile } = useStateCtx();
+
+ return (
+
+
+ {OpenProfile && }
+
+ );
};
export default NavBarAuthenticated;
diff --git a/v2/src/components/Loaders/Spinner.tsx b/v2/src/components/Loaders/Spinner.tsx
new file mode 100644
index 0000000..a77dcec
--- /dev/null
+++ b/v2/src/components/Loaders/Spinner.tsx
@@ -0,0 +1,27 @@
+import { cn } from '@/utils';
+
+type Props = {
+ color?: string;
+ innerColor?: string;
+};
+const LoadingSpinner = ({ color, innerColor }: Props) => (
+
+);
+
+export default LoadingSpinner;
diff --git a/v2/src/components/skelton/ExploreCardSkel.tsx b/v2/src/components/skelton/ExploreCardSkel.tsx
new file mode 100644
index 0000000..58b80fc
--- /dev/null
+++ b/v2/src/components/skelton/ExploreCardSkel.tsx
@@ -0,0 +1,30 @@
+import { cn } from '@/utils';
+import React from 'react';
+
+const ExploreCardSkel = () => {
+ return (
+ <>
+
+ >
+ );
+};
+
+export default ExploreCardSkel;
diff --git a/v2/src/components/ui/button.tsx b/v2/src/components/ui/button.tsx
index 3b837a2..7f017f6 100644
--- a/v2/src/components/ui/button.tsx
+++ b/v2/src/components/ui/button.tsx
@@ -3,7 +3,7 @@ import { VariantProps, cva } from 'class-variance-authority';
import { twMerge } from 'tailwind-merge';
import Link from 'next/link';
-const buttonVariants = cva(
+export const buttonVariants = cva(
'relative px-4 py-3 flex items-center justify-center gap-5 w-fit h-[48px] rounded-[16px] text-white-100',
{
variants: {
diff --git a/v2/src/components/ui/calendar.tsx b/v2/src/components/ui/calendar.tsx
new file mode 100644
index 0000000..900e2c8
--- /dev/null
+++ b/v2/src/components/ui/calendar.tsx
@@ -0,0 +1,66 @@
+"use client"
+
+import * as React from "react"
+import { ChevronLeft, ChevronRight } from "lucide-react"
+import { DayPicker } from "react-day-picker"
+
+import { cn } from "@/utils/index"
+import { buttonVariants } from "@/components/ui/button"
+
+export type CalendarProps = React.ComponentProps
+
+function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ ...props
+}: CalendarProps) {
+ return (
+ ,
+ IconRight: ({ ...props }) => ,
+ }}
+ {...props}
+ />
+ )
+}
+Calendar.displayName = "Calendar"
+
+export { Calendar }
diff --git a/v2/src/components/ui/popover.tsx b/v2/src/components/ui/popover.tsx
new file mode 100644
index 0000000..e2ca0f6
--- /dev/null
+++ b/v2/src/components/ui/popover.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import * as PopoverPrimitive from "@radix-ui/react-popover"
+
+import { cn } from "@/utils/index"
+
+const Popover = PopoverPrimitive.Root
+
+const PopoverTrigger = PopoverPrimitive.Trigger
+
+const PopoverContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+PopoverContent.displayName = PopoverPrimitive.Content.displayName
+
+export { Popover, PopoverTrigger, PopoverContent }
diff --git a/v2/src/context/ExploreCtx.tsx b/v2/src/context/ExploreCtx.tsx
new file mode 100644
index 0000000..2a4c98d
--- /dev/null
+++ b/v2/src/context/ExploreCtx.tsx
@@ -0,0 +1,131 @@
+'use client';
+
+import React, { SetStateAction, createContext, useContext, useLayoutEffect, useMemo, useState } from 'react';
+import { EventProps, CategoryProps } from '@/types';
+import { allevent, allcategories, geteventsbycategories } from '@/actions/expore';
+
+// Add Your Props here
+interface ExploreContextProps {
+ events: EventProps[];
+ setevents: React.Dispatch>;
+ eventsSearchTerm: string;
+ seteventsSearchTerm: React.Dispatch>;
+ categories: CategoryProps[];
+ setcategories: React.Dispatch>;
+ catLoading: boolean;
+ setcatLoading: React.Dispatch>;
+ eventsLoading: boolean;
+ seteventsLoading: React.Dispatch>;
+ selectedcategories: string;
+ setSelectedcategories: React.Dispatch>;
+}
+
+export const ExploreContext = createContext({} as ExploreContextProps);
+
+const ExploreContextProvider = ({ children }: { children: React.ReactNode }) => {
+ const [events, setevents] = useState([] as EventProps[]);
+ const [eventsSearchTerm, seteventsSearchTerm] = useState('');
+ const [categories, setcategories] = useState([] as CategoryProps[]);
+ const [catLoading, setcatLoading] = useState(false);
+ const [eventsLoading, seteventsLoading] = useState(false);
+ const [selectedcategories, setSelectedcategories] = useState('all');
+
+ useLayoutEffect(() => {
+ const fetchUserData = async () => {
+ try {
+ setcatLoading(true);
+ const cat = await allcategories();
+ if (cat?.status === 'success') {
+ console.log(cat.categories);
+ setcategories(cat.categories);
+ } else {
+ }
+ } catch (err) {
+ console.log(err);
+ } finally {
+ setcatLoading(false);
+ }
+ };
+
+ fetchUserData();
+ }, [categories]);
+
+ // useLayoutEffect(() => {
+ // const fetchEvents = async () => {
+ // try {
+ // seteventsLoading(true);
+ // const events = await allevent();
+ // if (events?.status === 'success') {
+ // console.log(events.events);
+ // setevents(events.events);
+ // } else {
+ // }
+ // } catch (err) {
+ // console.log(err);
+ // } finally {
+ // seteventsLoading(false);
+ // }
+ // };
+
+ // fetchEvents();
+ // }, [events]);
+ useLayoutEffect(() => {
+ const fetchEvents = async () => {
+ try {
+ seteventsLoading(true);
+
+ if (selectedcategories === 'all') {
+ // Fetch all events only when it is all
+ const allEventsResult = await allevent();
+ if (allEventsResult?.status === 'success') {
+ setevents(allEventsResult.events);
+ }
+ } else {
+ // Fetch events by selected category
+ const eventsByCategoryResult = await geteventsbycategories(selectedcategories);
+ if (eventsByCategoryResult?.status === 'success') {
+ setevents(eventsByCategoryResult.events);
+ }
+ }
+ } catch (err) {
+ console.log(err);
+ } finally {
+ seteventsLoading(false);
+ }
+ };
+
+ fetchEvents();
+ }, [selectedcategories]);
+
+ const value = useMemo(
+ () => ({
+ events,
+ setevents,
+ eventsSearchTerm,
+ seteventsSearchTerm,
+ categories,
+ setcategories,
+ catLoading,
+ setcatLoading,
+ eventsLoading,
+ seteventsLoading,
+ selectedcategories,
+ setSelectedcategories,
+ }),
+ [events, eventsSearchTerm, categories, selectedcategories],
+ );
+
+ return {children};
+};
+
+// Call this function whenever you want to use the context
+export const useExploreCtx = () => {
+ const ctx = useContext(ExploreContext);
+
+ if (!ctx) {
+ throw new Error('useExploreCtx must be used within a ExploreContextProvider');
+ }
+ return ctx;
+};
+
+export default ExploreContextProvider;
diff --git a/v2/src/context/StateCtx.tsx b/v2/src/context/StateCtx.tsx
index 2f49053..22435b0 100644
--- a/v2/src/context/StateCtx.tsx
+++ b/v2/src/context/StateCtx.tsx
@@ -5,12 +5,22 @@ import { createContext, useContext, useState, Dispatch, SetStateAction, useEffec
interface StateContextProps {
openMenu: boolean;
setopenMenu: Dispatch>;
+ OpenNotification: boolean;
+ setOpenNotification: Dispatch>;
+ OpenProfile: boolean;
+ setOpenProfile: Dispatch>;
}
const StateContext = createContext(undefined);
const StateCtxProvider = ({ children }: { children: React.ReactNode }) => {
const [openMenu, setopenMenu] = useState(false);
+ const [OpenNotification, setOpenNotification] = useState(false);
+ const [OpenProfile, setOpenProfile] = useState(false);
+
+ const isMobileDevice = () => {
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator?.userAgent);
+ };
useEffect(() => {
const t = '%c Made By \ud83d\udc9a - HNGX I10 ',
@@ -27,7 +37,10 @@ const StateCtxProvider = ({ children }: { children: React.ReactNode }) => {
console.log(t, n);
}, []);
- const value = useMemo(() => ({ openMenu, setopenMenu }), [openMenu]);
+ const value = useMemo(
+ () => ({ openMenu, setopenMenu, OpenNotification, setOpenNotification, OpenProfile, setOpenProfile }),
+ [openMenu, OpenNotification, OpenProfile],
+ );
return {children};
};
diff --git a/v2/src/context/UserCtx.tsx b/v2/src/context/UserCtx.tsx
new file mode 100644
index 0000000..a6a198c
--- /dev/null
+++ b/v2/src/context/UserCtx.tsx
@@ -0,0 +1,75 @@
+'use client';
+
+import React, { SetStateAction, createContext, useContext, useLayoutEffect, useMemo, useState } from 'react';
+import { User } from '@/types';
+import { useSession } from 'next-auth/react';
+import { getUser } from '@/actions/user';
+import { useRouter } from 'next/navigation';
+import { DEFAULT_REVALIDATE_REDIRECT } from '@/routes';
+
+// Add Your Props here
+interface UserContextProps {
+ user: User;
+ setUser: React.Dispatch>;
+}
+
+export const UserContext = createContext({} as UserContextProps);
+
+const UserContextProvider = ({ children }: { children: React.ReactNode }) => {
+ const initialUserDataState: User = {
+ userID: '',
+ email: '',
+ bio: '',
+ socialLinks: [],
+ profileImage: '/facemoji.png',
+ displayName: '',
+ firstName: '',
+ lastName: '',
+ slug: '',
+ role: '',
+ location: '',
+ coverImage: '',
+ isVerified: false,
+ };
+ // Add Your State(s) Here
+ const { data: session } = useSession();
+ const router = useRouter();
+ const [user, setUser] = useState(initialUserDataState);
+
+ useLayoutEffect(() => {
+ const fetchUserData = async () => {
+ try {
+ const user = await getUser();
+
+ if (user?.status === 'success') {
+ console.log('User came from Backend');
+ // console.log(user.user);
+ setUser(user.user);
+ } else if (user?.status === 401) {
+ router.push(DEFAULT_REVALIDATE_REDIRECT);
+ } else {
+ }
+ } catch (err) {}
+ };
+
+ fetchUserData();
+ }, [user]);
+
+ console.log(user);
+
+ const value = useMemo(() => ({ user, setUser }), [user]);
+
+ return {children};
+};
+
+// Call this function whenever you want to use the context
+export const useUserCtx = () => {
+ const ctx = useContext(UserContext);
+
+ if (!ctx) {
+ throw new Error('useUserCtx must be used within a UserContextProvider');
+ }
+ return ctx;
+};
+
+export default UserContextProvider;
diff --git a/v2/src/hooks/useVisible.ts b/v2/src/hooks/useVisible.ts
new file mode 100644
index 0000000..0a3d895
--- /dev/null
+++ b/v2/src/hooks/useVisible.ts
@@ -0,0 +1,22 @@
+import React, { useState, useEffect, useRef } from 'react';
+
+function useVisible() {
+ const [isVisible, setIsVisible] = useState(false);
+ const ref = useRef(null);
+
+ const handleClickOutside = (event: MouseEvent) => {
+ if (ref.current && !ref.current.contains(event.target as Node | null)) {
+ setIsVisible(false);
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener('click', handleClickOutside, true);
+ return () => {
+ document.removeEventListener('click', handleClickOutside, true);
+ };
+ }, []);
+ return { ref, isVisible, setIsVisible };
+}
+
+export default useVisible;
diff --git a/v2/src/modules/explore/Categories.tsx b/v2/src/modules/explore/Categories.tsx
new file mode 100644
index 0000000..488a78a
--- /dev/null
+++ b/v2/src/modules/explore/Categories.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import React from 'react';
+import { useExploreCtx } from '@/context/ExploreCtx';
+import { IoFootballOutline } from 'react-icons/io5';
+import { CiBasketball } from 'react-icons/ci';
+import { FaVolleyballBall, FaTableTennis } from 'react-icons/fa';
+import { GiBoxingGlove, GiWeightLiftingUp } from 'react-icons/gi';
+import { TbPlayHandball, TbSwimming } from 'react-icons/tb';
+import { MdOutlineSportsRugby, MdOutlineGolfCourse, MdSportsCricket, MdOutlineSportsTennis } from 'react-icons/md';
+import { IoBicycle } from 'react-icons/io5';
+import { RiSailboatFill } from 'react-icons/ri';
+import { GrRun } from 'react-icons/gr';
+import Button from '@/components/ui/button';
+import { cn } from '@/utils';
+
+const Categories = () => {
+ const catergoryIcon = [
+ { name: 'Basketball', icon: },
+ { name: 'Table Tennis', icon: },
+ { name: 'Volleyball', icon: },
+ { name: 'Wrestling', icon: },
+ { name: 'Cricket', icon: },
+ { name: 'Handball', icon: },
+ { name: 'Weightlifting', icon: },
+ { name: 'Badminton', icon: },
+ { name: 'Taekwondo', icon: },
+ { name: 'Judo', icon: },
+ { name: 'Tennis', icon: },
+ { name: 'Swimming', icon: },
+ { name: 'Rugby', icon: },
+ { name: 'Cycling', icon: },
+ { name: 'Golf', icon: },
+ { name: 'Dambe', icon: },
+ { name: 'Canoeing', icon: },
+ { name: 'Football', icon: },
+ { name: 'Athletics', icon: },
+ { name: 'Boxing', icon: },
+ ];
+
+ const getCategoryIcon = (categoryTitle: string) => {
+ const category = catergoryIcon.find((cat) => cat.name === categoryTitle);
+ return category ? category.icon : ;
+ };
+
+ const { categories, setSelectedcategories } = useExploreCtx();
+ return (
+
+
+
+ Category
+
+
+ {categories.map((category) => (
+
+ ))}
+
+
+
+ );
+};
+
+export default Categories;
diff --git a/v2/src/modules/explore/EventsGrid.tsx b/v2/src/modules/explore/EventsGrid.tsx
new file mode 100644
index 0000000..7520457
--- /dev/null
+++ b/v2/src/modules/explore/EventsGrid.tsx
@@ -0,0 +1,64 @@
+'use client';
+
+import { useState, Suspense } from 'react';
+import { useExploreCtx } from '@/context/ExploreCtx';
+import ExploreCard from '@/components/Cards/ExploreCard';
+import ExploreCardSkel from '@/components/skelton/ExploreCardSkel';
+import Button from '@/components/ui/button';
+import { cn } from '@/utils';
+
+const EventsGrid = () => {
+ const [limit, setLimit] = useState(6);
+ const { events, eventsSearchTerm } = useExploreCtx();
+
+ // Filter events based on the search term
+ const filteredEvents = events.filter(
+ (event) => eventsSearchTerm === '' || event.title!.toLowerCase().includes(eventsSearchTerm.toLowerCase()),
+ );
+
+ const hasSearchResults = filteredEvents.length > 0;
+ return (
+ <>
+
+
Discover
+
Popular Events
+
+
+ {filteredEvents.length}
+
+
+ {hasSearchResults ? `Search Result${filteredEvents.length > 1 ? 's' : ''} for` : 'No Results for'}{' '}
+ "{eventsSearchTerm}"
+
+
+
+ {filteredEvents.slice(0, limit).map((event) => (
+ }>
+
+
+ ))}
+
+ {limit < events.length && (
+
+ )}
+
+ >
+ );
+};
+
+export default EventsGrid;
diff --git a/v2/src/modules/explore/Hero.tsx b/v2/src/modules/explore/Hero.tsx
new file mode 100644
index 0000000..4721da0
--- /dev/null
+++ b/v2/src/modules/explore/Hero.tsx
@@ -0,0 +1,89 @@
+'use client';
+
+import React from 'react';
+import { cn } from '@/utils';
+import Image from 'next/image';
+import { useExploreCtx } from '@/context/ExploreCtx';
+import { FormInput } from '@/components/ui/FormInput';
+import { SearchNormal } from 'iconsax-react';
+import { X } from 'lucide-react';
+
+
+const Hero = () => {
+ const { seteventsSearchTerm, eventsSearchTerm } = useExploreCtx();
+ return (
+
+
+
+
+
+ Finding Events Have Never been{' '}
+ Easier
+
+
+ Embark on a journey of personalized event discovery with Evento's unique recommendation engine. As you
+ scroll through the Explore Page, immerse yourself in a finely curated feed of events meticulously crafted to
+ align seamlessly with your individual preferences, location, and favorite categories.
+
+
+
+
+ seteventsSearchTerm(e.target.value)}
+ value={eventsSearchTerm}
+ type="text"
+ placeholder="Search via events name..."
+ className=" mt-1 mb-3 p-[16px] w-full text-black h-[60px] border text-md font-medium rounded-md font-Worksans"
+ />
+ {eventsSearchTerm.length === 0 && (
+
+
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+export default Hero;
diff --git a/v2/src/routes.ts b/v2/src/routes.ts
index 8d77c1d..20fe804 100644
--- a/v2/src/routes.ts
+++ b/v2/src/routes.ts
@@ -3,3 +3,9 @@
* @type {string}
*/
export const DEFAULT_LOGIN_REDIRECT = '/dashboard';
+
+/**
+ * The default redirect when user is not authenticated
+ * @type {string}
+ */
+export const DEFAULT_REVALIDATE_REDIRECT = '/auth/sign-in';
diff --git a/v2/src/styles/globals.scss b/v2/src/styles/globals.scss
index cbb047f..192eacf 100644
--- a/v2/src/styles/globals.scss
+++ b/v2/src/styles/globals.scss
@@ -25,6 +25,11 @@
background: #e0580c;
}
+.dark ::selection {
+ color: rgb(201, 191, 2);
+ background: #011724;
+}
+
#parent {
position: relative !important;
}
@@ -64,3 +69,10 @@
transform: scale(1);
}
}
+
+
+.card-shadow {
+ box-shadow:
+ 0px 1px 2px 0px rgba(16, 24, 40, 0.06),
+ 0px 1px 3px 0px rgba(16, 24, 40, 0.1);
+}
\ No newline at end of file
diff --git a/v2/src/types/index.d.ts b/v2/src/types/index.d.ts
index bb7894d..91cae07 100644
--- a/v2/src/types/index.d.ts
+++ b/v2/src/types/index.d.ts
@@ -56,113 +56,72 @@ export interface UploadParams {
file: File;
}
-export interface EventPayload {
- title: string;
- description: string;
- imageURL: string;
- startDate: string;
- endDate: string;
- locationType: 'Physical' | 'Virtual';
- location?: string;
- virtualLocationLink?: string;
- time?: string;
- capacity: number;
- eventType: string;
- organizerID: string;
- categoryName: string;
- ticketType: string;
- ticketPrice: number;
- entranceFee?: number;
- ticketID?: string;
-}
-
-export interface EventParticipant {
- userID: string;
- email: string;
- profileImage: string | null;
- firstName: string;
- lastName: string;
-}
-
-export interface EventsProps {
- eventID: string;
- title: string;
- description: string;
- imageURL: string;
- startDate: string;
- endDate: string;
- time: string;
- location: string;
- capacity: number;
- entranceFee: number;
- eventType: string;
- organizerID: string;
- categoryCategoryID: string;
- participants: EventParticipant[];
- tickets: {
- ticketID: string;
- ticketPrice: number;
- ticketType: string;
- }[];
-}
-
-export interface UserProfile2 {
+export interface User {
userID?: string;
email?: string;
bio?: string;
-
- profileImage?: string | Blob | File;
+ socialLinks?: socialLinks[];
+ profileImage?: string;
displayName?: string;
firstName?: string;
lastName?: string;
slug?: string;
role?: string;
location?: string;
+ coverImage?: string;
+ isVerified?: boolean;
}
-export interface UserProfile {
- userID: string;
- email: string;
- bio: string;
- coverImage?: string;
+export interface Notification {
+ id: number;
+ text: string;
+ read: boolean;
+ date: string;
+}
- profileImage: string;
- displayName: string;
- firstName: string;
- lastName: string;
- slug: string;
- role: string;
- location: string;
+export interface NotificationsProps {
+ unreadNotifications: (count: number) => void;
+ notificationsRef: React.RefObject;
+ notifications: NotificationProps[];
}
-export interface socialLinks {
- facebookURL?: string;
- instagramURL?: string;
- twitterURL?: string;
- websiteURL?: string;
+
+interface Participant {
+ userID?: string;
+ email?: string;
+ profileImage?: string;
+ firstName?: string;
+ lastName?: string;
}
-export type participantType = {
- userID: string;
- email: string;
- profileImage: string | null;
- firstName: string;
- lastName: string;
-};
+interface Ticket {
+ ticketID: string;
+ ticketType: string;
+ ticketPrice: number;
+}
-export type eventType = {
+export interface EventProps {
eventID?: string;
+ eventSlug?: string;
title?: string;
description?: string;
imageURL?: string;
- startDate: string;
+ startDate?: string;
endDate?: string;
- time?: string;
+ locationType?: string;
location?: string;
- locationType: string;
+ virtualLocationLink?: string;
capacity?: number;
- entranceFee?: number;
- eventType?: string;
- organizerID: string;
+ organizerID?: string;
categoryCategoryID?: string;
- participants?: participantType[];
-};
\ No newline at end of file
+ participants?: Participant[];
+ Category?: {
+ categoryID?: string;
+ name?: string;
+ };
+ tickets?: Ticket[];
+}
+
+export interface CategoryProps {
+ categoryID: string;
+ name: string;
+}
diff --git a/v2/src/utils/index.ts b/v2/src/utils/index.ts
index d084cca..9825477 100644
--- a/v2/src/utils/index.ts
+++ b/v2/src/utils/index.ts
@@ -1,6 +1,36 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
+}
+
+/**
+ * Convert a UTC date string to local time and return an array of formatted date and time parts.
+ *
+ * @param {string} utcDateString - The input UTC date string.
+ * @returns {string[]} - An array containing formatted date and time parts.
+ */
+
+export function convertUTCtoLocalTime(utcDateString: string): string[] {
+ const utcDate = new Date(utcDateString);
+ const localDate = new Date(utcDate.getTime() + utcDate.getTimezoneOffset() * 60000);
+
+ // Options for formatting the date and time
+ const options: Intl.DateTimeFormatOptions = {
+ weekday: 'short',
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ timeZoneName: 'short',
+ };
+
+ // Format the local date and time and split into an array
+ const formattedTime: string[] = localDate.toLocaleString('en-US', options).split(', ');
+
+ // Return the array containing formatted date and time parts
+ return formattedTime;
}