diff --git a/frontend/app/(auth)/sign-in.jsx b/frontend/app/(auth)/sign-in.jsx index 8a17065..941bb91 100644 --- a/frontend/app/(auth)/sign-in.jsx +++ b/frontend/app/(auth)/sign-in.jsx @@ -13,6 +13,8 @@ const SignIn = () => { password: '' }) + const isWeb = Platform.OS === 'web' + const [isSubmitting, setisSubmitting] = useState(false) const [message, setMessage] = useState('') @@ -26,7 +28,10 @@ const SignIn = () => { useEffect(() => { if (isLoggedIn) { - router.replace('/home') + if (isWeb) + window.location.href = '/home' + else + router.replace('/home'); } if (username) { @@ -69,11 +74,17 @@ const SignIn = () => { .catch(err => { console.log(err) setIsLoading(false) - Alert.alert('Internal Server Error. Try again later') setForm({ username: '', password: '' }) + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) } @@ -83,7 +94,7 @@ const SignIn = () => { behavior={Platform.OS === 'ios' ? 'padding' : 'height'} > - + Log in to MedShop {message} { Sign Up + router.push('/home')} + containerStyles='mt-7 w-48 self-center' + isLoading={isSubmitting} + /> {isLoading && ( diff --git a/frontend/app/(auth)/sign-up.jsx b/frontend/app/(auth)/sign-up.jsx index 3a71da5..40eb118 100644 --- a/frontend/app/(auth)/sign-up.jsx +++ b/frontend/app/(auth)/sign-up.jsx @@ -15,6 +15,8 @@ const SignUp = () => { password: '' }) + const isWeb = Platform.OS === 'web' + const [isSubmitting, setisSubmitting] = useState(false) const [message, setMessage] = useState('') @@ -25,7 +27,10 @@ const SignUp = () => { useEffect(() => { if (isLoggedIn) { - router.replace('/home') + if (isWeb) + window.location.href = '/home' + else + router.replace('/home'); } }, []) @@ -44,7 +49,12 @@ const SignUp = () => { setIsLoading(false) if (data.message == 'Registration successful') { - alert('Account created successfully! You can now sign in') + const message = 'Account created successfully! You can now sign in' + if (isWeb){ + window.alert(message) + } else { + alert(message) + } router.replace(`/sign-in?username=${form.username}`) } else { setMessage(`${data.message}! ${data.details}`) @@ -57,12 +67,18 @@ const SignUp = () => { .catch(err => { console.log(err) setIsLoading(false) - Alert.alert('Internal Server Error. Try again later') setForm({ username: '', email: '', password: '' }) + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) } @@ -72,7 +88,7 @@ const SignUp = () => { behavior={Platform.OS === 'ios' ? 'padding' : 'height'} > - + Register to MedShop {message} { Sign In + router.push('/home')} + containerStyles='mt-7 w-48 self-center' + isLoading={isSubmitting} + /> {isLoading && ( diff --git a/frontend/app/(tabs)/(products)/home.jsx b/frontend/app/(tabs)/(products)/home.jsx index 403927c..fff9411 100644 --- a/frontend/app/(tabs)/(products)/home.jsx +++ b/frontend/app/(tabs)/(products)/home.jsx @@ -1,13 +1,13 @@ -import { View, Text, ScrollView, Alert, ActivityIndicator } from 'react-native' +import { View, Text, ScrollView, Alert, ActivityIndicator, Platform } from 'react-native' import React, { useEffect, useState } from 'react' import { SafeAreaView } from 'react-native-safe-area-context' -import { images } from '../../../constants' import Item from '../../../components/Item' import { router } from 'expo-router' -import { useGlobalContext } from '../../../context/GlobalProvider' import { API_URL } from '../../_layout' const Home = () => { + const isWeb = Platform.OS === 'web' + const [ products, setProducts ] = useState([]) const [isLoading, setIsLoading] = useState(false) @@ -16,7 +16,7 @@ const Home = () => { setIsLoading(true) - fetch(`${API_URL}/products`, { + fetch(`${API_URL}/products/`, { method: 'GET', headers: { 'Content-Type': 'application/json' @@ -27,7 +27,13 @@ const Home = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -47,12 +53,14 @@ const Home = () => { return ( - - {products.length > 0 ? 'All products:' : 'No products available'} - - - {productItems} - + + + {products.length > 0 ? 'All products:' : 'No products available'} + + + {productItems} + + {isLoading && ( diff --git a/frontend/app/(tabs)/(products)/product-details.jsx b/frontend/app/(tabs)/(products)/product-details.jsx index 7450e35..cc1ee33 100644 --- a/frontend/app/(tabs)/(products)/product-details.jsx +++ b/frontend/app/(tabs)/(products)/product-details.jsx @@ -1,4 +1,4 @@ -import { View, Text, ScrollView, Image, Alert, ActivityIndicator } from 'react-native' +import { View, Text, ScrollView, Image, Alert, ActivityIndicator, Platform } from 'react-native' import React, { useEffect, useState } from 'react' import { SafeAreaView } from 'react-native-safe-area-context' import CustomButton from '../../../components/CustomButton' @@ -29,6 +29,8 @@ const ProductDetails = () => { const [decreaseDisabled, setDecreaseDisabled] = useState(true) + const isWeb = Platform.OS === 'web' + useEffect(() => { setIsLoading(true) @@ -50,7 +52,12 @@ const ProductDetails = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) + window.alert(message) + else + Alert.alert(message) }) setIsLoading(false) @@ -62,7 +69,7 @@ const ProductDetails = () => { if (/^\d{1,3}$/.test(text) && parseInt(text) >= 1 && parseInt(text) <= 999) { setValue(text); } - console.log(value); + setIncreaseDisabled(text == '999'); setDecreaseDisabled(text == '1'); } @@ -81,7 +88,6 @@ const ProductDetails = () => { setValue(newValue.toString()); - console.log(newValue == '1'); setIncreaseDisabled(newValue == '999'); setDecreaseDisabled(newValue == '1'); } @@ -89,21 +95,31 @@ const ProductDetails = () => { const addToCart = () => { if (!isLoggedIn) { - Alert.alert( - "Sign in required", - "You need to be signed in to add to cart. Do you want to sign in now?", - [ - { - text: "No", - onPress: () => {} - }, - { - text: "Yes", - onPress: () => router.push('/sign-in') - }, - ], - { cancelable: true } - ); + + const message = "You need to be signed in to add to cart. Do you want to sign in now?" + + if (isWeb) { + const confirm = window.confirm(message) + + if (confirm) router.push('/sign-in'); + } else { + Alert.alert( + "Sign in required", + message, + [ + { + text: "No", + onPress: () => {} + }, + { + text: "Yes", + onPress: () => router.push('/sign-in') + }, + ], + { cancelable: true } + ); + } + return; } @@ -127,40 +143,55 @@ const ProductDetails = () => { triggerRefreshViews(); setIsLoading(false) - Alert.alert( - "Product added to cart", - "Product added to cart. Do you want to continue to checkout?", - [ - { - text: "No", - onPress: () => {} - }, - { - text: "Yes", - onPress: () => router.push('/cart') - }, - ], - { cancelable: true } - ); + const message = "Product added to cart. Do you want to continue to checkout?" + + if (isWeb) { + const confirm = window.confirm(message) + + if (confirm) router.push('/cart'); + } else { + Alert.alert( + "Product added to cart", + message, + [ + { + text: "No", + onPress: () => {} + }, + { + text: "Yes", + onPress: () => router.push('/cart') + }, + ], + { cancelable: true } + ); + } + }) .catch(err => { setIsLoading(false) console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb){ + window.alert(message) + } else { + Alert.alert(message) + } }) } return ( - + {productInfo.imageUrl ? : diff --git a/frontend/app/(tabs)/(profile)/order-details.jsx b/frontend/app/(tabs)/(profile)/order-details.jsx index a59b6a2..3b59b64 100644 --- a/frontend/app/(tabs)/(profile)/order-details.jsx +++ b/frontend/app/(tabs)/(profile)/order-details.jsx @@ -1,4 +1,4 @@ -import { View, Text, ScrollView, ActivityIndicator } from 'react-native' +import { View, Text, ScrollView, ActivityIndicator, Platform } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' import React, { useState, useEffect } from 'react' import OrderedProductItem from '../../../components/OrderedProductItem' @@ -11,6 +11,8 @@ const OrderDetails = () => { const { orderId } = useLocalSearchParams() + const isWeb = Platform.OS === 'web' + const { state, isLoggedIn, refreshViews } = useGlobalContext() const [orderInfo, setOrderInfo] = useState({ @@ -27,7 +29,10 @@ const OrderDetails = () => { useEffect(() => { if (!isLoggedIn) { - router.push('/home') + if (isWeb) + window.location.href = '/home' + else + router.replace('/home'); return } @@ -48,11 +53,18 @@ const OrderDetails = () => { total: data.order.amount, date: formatDate(data.order.created_at) }) + setOrderedProducts(data.order.items) }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -74,7 +86,7 @@ const OrderDetails = () => { return ( - + Order information: Order number: diff --git a/frontend/app/(tabs)/(profile)/profile.jsx b/frontend/app/(tabs)/(profile)/profile.jsx index f862057..06ece6c 100644 --- a/frontend/app/(tabs)/(profile)/profile.jsx +++ b/frontend/app/(tabs)/(profile)/profile.jsx @@ -1,4 +1,4 @@ -import { View, Text, ScrollView, Alert, ActivityIndicator } from 'react-native' +import { View, Text, ScrollView, Alert, ActivityIndicator, Platform } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' import React, { useEffect, useState } from 'react' import { router } from 'expo-router' @@ -13,6 +13,8 @@ const Profile = () => { const [orders, setOrders] = useState([]) + const isWeb = Platform.OS === 'web' + const [profileInfo, setProfileInfo] = useState({ username: '', email: '', @@ -43,7 +45,13 @@ const Profile = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) fetch(`${API_URL}/payment/orders`, { @@ -58,7 +66,13 @@ const Profile = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -67,28 +81,43 @@ const Profile = () => { const handleSignOut = () => { -Alert.alert( - "Confirm SignOut", - "Are you sure you want to sign out?", - [ - { - text: "No", - onPress: () => {} - }, - { - text: "Yes", - onPress: () => { - setIsLoggedIn(false) - setState({ - token: '', - }) - - router.replace('/home') - } - }, - ], - { cancelable: true } - ); + const message = "Are you sure you want to sign out?" + + if (isWeb) { + const confirm = window.confirm(message) + + if (confirm) { + setIsLoggedIn(false) + setState({ + token: '', + }) + + router.replace('/home') + } + } else { + Alert.alert( + "Confirm SignOut", + message, + [ + { + text: "No", + onPress: () => {} + }, + { + text: "Yes", + onPress: () => { + setIsLoggedIn(false) + setState({ + token: '', + }) + + router.replace('/home') + } + }, + ], + { cancelable: true } + ); + } } const orderItems = orders.map(order => ( @@ -106,12 +135,12 @@ Alert.alert( {isLoggedIn ? - + Your profile: @@ -129,7 +158,7 @@ Alert.alert( } : - + { source={icon} resizeMode='contain' tintColor={color} - className='w-6 h-6' + className='w-6 h-6 max-w-[50px] max-h-[50px]' /> {name} @@ -34,7 +34,7 @@ const TabsLayout = () => { backgroundColor: '#ffffff', borderTopWidth: 1, borderTopColor: '#ffffff', - height: 84, + height: Platform.OS === 'web' ? 120 : 84, paddingTop: 10, shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, @@ -46,6 +46,7 @@ const TabsLayout = () => { > ( { }} /> ( { + const router = useRouter() + + const isWeb = Platform.OS === 'web' + const { isLoggedIn, state, refreshViews, triggerRefreshViews } = useGlobalContext() const [isLoading, setIsLoading] = useState(false) @@ -19,12 +21,17 @@ const Cart = () => { const [total, setTotal] = useState('') + useEffect(() => { setIsLoading(true) if (!isLoggedIn) { - router.replace('/home'); + + if (isWeb) + window.location.href = '/home' + else + router.replace('/home'); return; } @@ -42,7 +49,13 @@ const Cart = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -53,40 +66,80 @@ const Cart = () => { if (showAlert) { - Alert.alert( - "Remove Product", - "Are you sure you want to remove this product from cart?", - [ - { - text: "No", - onPress: () => {} - }, - { - text: "Yes", - onPress: () => { - setIsLoading(true) - - fetch(`${API_URL}/cart/remove/${cartId}?quantity=${quantity}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${state.token}` - }, - }).then(res => res.json()) - .then(data => { - triggerRefreshViews() - }) - .catch(err => { - console.log(err) - Alert.alert('Internal Server Error. Try again later') - }) + const message = "Are you sure you want to remove this product from cart?" + + if (isWeb) { + const confirm = window.confirm(message) + + if (confirm) { + setIsLoading(true) + + fetch(`${API_URL}/cart/remove/${cartId}?quantity=${quantity}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${state.token}` + }, + }).then(res => res.json()) + .then(data => { + triggerRefreshViews() + }) + .catch(err => { + console.log(err) + + const errorMessage = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(errorMessage) + } else { + Alert.alert(errorMessage) + } + }) + + setIsLoading(false) + } + } else { + Alert.alert( + "Remove Product", + message, + [ + { + text: "No", + onPress: () => {} + }, + { + text: "Yes", + onPress: () => { + setIsLoading(true) + + fetch(`${API_URL}/cart/remove/${cartId}?quantity=${quantity}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${state.token}` + }, + }).then(res => res.json()) + .then(data => { + triggerRefreshViews() + }) + .catch(err => { + console.log(err) + + const errorMessage = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(errorMessage) + } else { + Alert.alert(errorMessage) + } + }) + + setIsLoading(false) + } + }, + ], + { cancelable: true } + ); + } - setIsLoading(false) - } - }, - ], - { cancelable: true } - ); } else { @@ -101,11 +154,16 @@ const Cart = () => { }).then(res => res.json()) .then(data => { triggerRefreshViews() - console.log(data) }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const errorMessage = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -136,7 +194,13 @@ const Cart = () => { }) .catch(err => { console.log(err) - Alert.alert('Internal Server Error. Try again later') + + const message = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(message) + } else { + Alert.alert(message) + } }) setIsLoading(false) @@ -145,44 +209,100 @@ const Cart = () => { const handleCheckout = () => { - Alert.alert( - "Confirm Checkout", - "Are you sure you want to checkout?", - [ - { - text: "No", - onPress: () => {} - }, - { - text: "Yes", - onPress: () => { - setIsLoading(true) - - fetch(`${API_URL}/payment/checkout`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${state.token}` - }, - }).then(res => res.json()) - .then(data => { - - triggerRefreshViews(); - - Alert.alert('Checkout successful. Check your email for order details or go to Profile'); - - }) - .catch(err => { - console.log(err) - Alert.alert('Internal Server Error. Try again later') - }) - - setIsLoading(false) - } - }, - ], - { cancelable: true } - ); + const message = "Are you sure you want to checkout?" + + if (isWeb) { + const confirm = window.confirm(message) + + if (confirm) { + setIsLoading(true) + + fetch(`${API_URL}/payment/checkout`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${state.token}` + }, + }).then(res => res.json()) + .then(data => { + + triggerRefreshViews(); + + const infoMessage = 'Checkout successful. Check your email for order details or go to Profile' + + if (isWeb) { + window.alert(infoMessage) + } else { + Alert.alert(infoMessage); + } + + }) + .catch(err => { + console.log(err) + + const errorMesssage = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(errorMesssage) + } else { + Alert.alert(errorMesssage) + } + }) + + setIsLoading(false) + } + } else { + Alert.alert( + "Confirm Checkout", + message, + [ + { + text: "No", + onPress: () => {} + }, + { + text: "Yes", + onPress: () => { + setIsLoading(true) + + fetch(`${API_URL}/payment/checkout`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${state.token}` + }, + }).then(res => res.json()) + .then(data => { + + triggerRefreshViews(); + + const infoMessage = 'Checkout successful. Check your email for order details or go to Profile' + + if (isWeb) { + window.alert(infoMessage) + } else { + Alert.alert(infoMessage); + } + + }) + .catch(err => { + console.log(err) + + const errorMesssage = 'Internal Server Error. Try again later' + if (isWeb) { + window.alert(errorMesssage) + } else { + Alert.alert(errorMesssage) + } + }) + + setIsLoading(false) + } + }, + ], + { cancelable: true } + ); + } + } @@ -202,7 +322,7 @@ const Cart = () => { return ( - + Your cart: {cartItems} {products.length === 0 ? diff --git a/frontend/app/_layout.jsx b/frontend/app/_layout.jsx index 8dafd2f..3fa19d0 100644 --- a/frontend/app/_layout.jsx +++ b/frontend/app/_layout.jsx @@ -1,4 +1,4 @@ -import { SplashScreen, Stack } from 'expo-router' +import { Stack, Slot } from 'expo-router' import '../global.css' import GlobalProvider from '../context/GlobalProvider' diff --git a/frontend/app/index.jsx b/frontend/app/index.jsx index 1aeab6a..20bcda2 100644 --- a/frontend/app/index.jsx +++ b/frontend/app/index.jsx @@ -1,4 +1,4 @@ -import { View, Text, ScrollView, Button } from 'react-native' +import { View, Text, ScrollView } from 'react-native' import React from 'react' import { SafeAreaView } from 'react-native-safe-area-context' import CustomButton from '../components/CustomButton' diff --git a/frontend/components/CartItem.jsx b/frontend/components/CartItem.jsx index 32ebf35..0406bf8 100644 --- a/frontend/components/CartItem.jsx +++ b/frontend/components/CartItem.jsx @@ -1,4 +1,4 @@ -import { View, Text, Image, TouchableOpacity, ActivityIndicator } from 'react-native' +import { View, Text, Image, Platform, ActivityIndicator } from 'react-native' import { useState, useEffect } from 'react' import { icons, images } from '../constants' import QuantityPicker from './QuantityPicker' @@ -12,11 +12,15 @@ const CartItem = ( { name, price, quantity, image, handleDelete, handleAdd } ) = const [decreaseDisabled, setDecreaseDisabled] = useState(parseInt(quantity) == 1); + useEffect(() => { + setValue(quantity.toString()) + }, [quantity]) + const handleInputChange = (text) => { if (/^\d{1,3}$/.test(text) && parseInt(text) >= 1 && parseInt(text) <= 999) { setValue(text); } - console.log(value); + setIncreaseDisabled(text == '999'); setDecreaseDisabled(text == '1'); } @@ -51,12 +55,12 @@ const CartItem = ( { name, price, quantity, image, handleDelete, handleAdd } ) = : } - + {name} {price} zł handleDelete(value, true)} /> diff --git a/frontend/components/FormField.jsx b/frontend/components/FormField.jsx index 90965bf..b174192 100644 --- a/frontend/components/FormField.jsx +++ b/frontend/components/FormField.jsx @@ -1,4 +1,4 @@ -import { View, Text, TextInput, TouchableOpacity, Image } from 'react-native' +import { View, Text, TextInput, TouchableOpacity, Image, Platform } from 'react-native' import React, { useState } from 'react' import { icons } from '../constants' @@ -8,12 +8,12 @@ const FormField = ({title, value, placeholder, handleChangeText, otherStyles, .. return ( - {title} + {title} setshowPassword(!showPassword)}> diff --git a/frontend/components/Item.jsx b/frontend/components/Item.jsx index 205516b..f90b691 100644 --- a/frontend/components/Item.jsx +++ b/frontend/components/Item.jsx @@ -4,14 +4,14 @@ import React from 'react' const Item = ({ name, price, image, itemId, onClick }) => { return ( {name} {price} zł diff --git a/frontend/components/OrderedProductItem.jsx b/frontend/components/OrderedProductItem.jsx index 8f78877..1d275e3 100644 --- a/frontend/components/OrderedProductItem.jsx +++ b/frontend/components/OrderedProductItem.jsx @@ -18,7 +18,7 @@ const OrderedProductItem = ({ name, quantity, price, total, image, onClick }) => : } - + {name} {quantity} x {price} zł diff --git a/frontend/components/QuantityPicker.jsx b/frontend/components/QuantityPicker.jsx index 32c09fc..829c403 100644 --- a/frontend/components/QuantityPicker.jsx +++ b/frontend/components/QuantityPicker.jsx @@ -1,24 +1,25 @@ -import { View, TextInput, Image, TouchableOpacity } from 'react-native' +import { View, TextInput, Image, TouchableOpacity, Platform } from 'react-native' import { useState } from 'react' import { icons } from '../constants' const QuantityPicker = ({ value, increaseDisabled, decreaseDisabled, handleInputChange, increaseValue, decreaseValue }) => { return ( - + diff --git a/frontend/context/GlobalProvider.js b/frontend/context/GlobalProvider.js index c78e1e5..e107de8 100644 --- a/frontend/context/GlobalProvider.js +++ b/frontend/context/GlobalProvider.js @@ -1,34 +1,52 @@ import { createContext, useState, useContext, useEffect } from "react"; +import { Platform } from "react-native"; const GlobalContext = createContext(); export const useGlobalContext = () => useContext(GlobalContext); const GlobalProvider = ({ children }) => { - - const [isLoggedIn, setIsLoggedIn] = useState(false); - - const [state, setState] = useState({ - token: '', - }); - - const [refreshViews, setRefreshViews] = useState(false); - - const triggerRefreshViews = () => setRefreshViews(!refreshViews); - - return ( - - {children} - - ); -} - -export default GlobalProvider; \ No newline at end of file + // Initialize state from sessionStorage or default values + const getInitialState = () => { + const savedState = Platform.OS === 'web' ? sessionStorage.getItem('globalState') : ''; + return savedState ? JSON.parse(savedState) : { token: '' }; + }; + + const getInitialLoginState = () => { + const savedLogin = Platform.OS === 'web' ? sessionStorage.getItem('isLoggedIn') : ''; + return savedLogin ? JSON.parse(savedLogin) : false; + }; + + const [isLoggedIn, setIsLoggedIn] = useState(getInitialLoginState); + const [state, setState] = useState(getInitialState); + const [refreshViews, setRefreshViews] = useState(false); + + const triggerRefreshViews = () => setRefreshViews(!refreshViews); + + // Persisting the state to sessionStorage whenever it changes + useEffect(() => { + if (Platform.OS === 'web') + sessionStorage.setItem('globalState', JSON.stringify(state)); + }, [state]); + + useEffect(() => { + if (Platform.OS === 'web') + sessionStorage.setItem('isLoggedIn', JSON.stringify(isLoggedIn)); + }, [isLoggedIn]); + + return ( + + {children} + + ); +}; + +export default GlobalProvider; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f91f334..0424630 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "react-native-reanimated": "^3.16.6", "react-native-safe-area-context": "^4.12.0", "react-native-screens": "~4.4.0", + "react-native-web": "~0.19.13", "tailwindcss": "^3.4.17" }, "devDependencies": { @@ -5001,6 +5002,14 @@ "node": ">=8" } }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -5739,6 +5748,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-loops": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==" + }, "node_modules/fast-uri": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", @@ -6281,6 +6295,11 @@ "node": ">=10.17.0" } }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -6378,6 +6397,15 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inline-style-prefixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz", + "integrity": "sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==", + "dependencies": { + "css-in-js-utils": "^3.1.0", + "fast-loops": "^1.1.3" + } + }, "node_modules/internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -9248,6 +9276,35 @@ "react-native": "*" } }, + "node_modules/react-native-web": { + "version": "0.19.13", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", + "integrity": "sha512-etv3bN8rJglrRCp/uL4p7l8QvUNUC++QwDbdZ8CB7BvZiMvsxfFIRM1j04vxNldG3uo2puRd6OSWR3ibtmc29A==", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@react-native/normalize-colors": "^0.74.1", + "fbjs": "^3.0.4", + "inline-style-prefixer": "^6.0.1", + "memoize-one": "^6.0.0", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "styleq": "^0.1.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-native-web/node_modules/@react-native/normalize-colors": { + "version": "0.74.88", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.88.tgz", + "integrity": "sha512-He5oTwPBxvXrxJ91dZzpxR7P+VYmc9IkJfhuH8zUiU50ckrt+xWNjtVugPdUv4LuVjmZ36Vk2EX8bl1gVn2dVA==" + }, + "node_modules/react-native-web/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", @@ -10300,6 +10357,11 @@ "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==" }, + "node_modules/styleq": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", + "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index f52b4d9..5b61d0a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,7 +20,8 @@ "react-native-reanimated": "^3.16.6", "react-native-safe-area-context": "^4.12.0", "react-native-screens": "~4.4.0", - "tailwindcss": "^3.4.17" + "tailwindcss": "^3.4.17", + "react-native-web": "~0.19.13" }, "devDependencies": { "@babel/core": "^7.20.0"