-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* #feat: added image_url to cart and order endpoints and updated seeders * Initial frontend commit * feat: added constants * feat: implemented GlobalProvider * feat: added auth view * feat: implemented sign-in and sign-up * feat: added tabs route * feat: implemented cart * feat: implemented products and products-details * feat: implemented profile and order details * feat: implemented custom button components * feat: implemented custom form field * feat: implemented order components
- Loading branch information
Showing
48 changed files
with
13,103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files | ||
|
||
# dependencies | ||
node_modules/ | ||
|
||
# Expo | ||
.expo/ | ||
dist/ | ||
web-build/ | ||
expo-env.d.ts | ||
|
||
# Native | ||
*.orig.* | ||
*.jks | ||
*.p8 | ||
*.p12 | ||
*.key | ||
*.mobileprovision | ||
|
||
# Metro | ||
.metro-health-check* | ||
|
||
# debug | ||
npm-debug.* | ||
yarn-debug.* | ||
yarn-error.* | ||
|
||
# macOS | ||
.DS_Store | ||
*.pem | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# typescript | ||
*.tsbuildinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"expo": { | ||
"name": "pharmacy_app", | ||
"slug": "pharmacy_app", | ||
"scheme": "pharmacy_app", | ||
"version": "1.0.0", | ||
"orientation": "portrait", | ||
"icon": "./assets/icon.png", | ||
"userInterfaceStyle": "light", | ||
"newArchEnabled": true, | ||
"splash": { | ||
"image": "./assets/splash-icon.png", | ||
"resizeMode": "contain", | ||
"backgroundColor": "#ffffff" | ||
}, | ||
"ios": { | ||
"supportsTablet": true | ||
}, | ||
"android": { | ||
"adaptiveIcon": { | ||
"foregroundImage": "./assets/adaptive-icon.png", | ||
"backgroundColor": "#ffffff" | ||
} | ||
}, | ||
"web": { | ||
"favicon": "./assets/favicon.png" | ||
}, | ||
"plugins": [ | ||
"expo-router" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { View, Text } from 'react-native' | ||
import React from 'react' | ||
import { Stack } from 'expo-router' | ||
|
||
const AuthLayout = () => { | ||
return ( | ||
<Stack> | ||
<Stack.Screen | ||
name='sign-in' | ||
options={{ | ||
headerShown: false | ||
}} | ||
/> | ||
<Stack.Screen | ||
name='sign-up' | ||
options={{ | ||
headerShown: false | ||
}} | ||
/> | ||
</Stack> | ||
) | ||
} | ||
|
||
export default AuthLayout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { View, Text, ScrollView, ActivityIndicator, Alert, KeyboardAvoidingView, Platform } from 'react-native' | ||
import React, { useState, useEffect } from 'react' | ||
|
||
import FormField from '../../components/FormField' | ||
import CustomButton from '../../components/CustomButton' | ||
import { useGlobalContext } from '../../context/GlobalProvider' | ||
import { Link, router, useLocalSearchParams } from 'expo-router' | ||
import { API_URL } from '../_layout' | ||
|
||
const SignIn = () => { | ||
const [form, setForm] = useState({ | ||
username: '', | ||
password: '' | ||
}) | ||
|
||
const [isSubmitting, setisSubmitting] = useState(false) | ||
|
||
const [message, setMessage] = useState('') | ||
|
||
const [isLoading, setIsLoading] = useState(false) | ||
|
||
const { isLoggedIn, setIsLoggedIn, setState } = useGlobalContext() | ||
|
||
const { username } = useLocalSearchParams() | ||
|
||
useEffect(() => { | ||
|
||
if (isLoggedIn) { | ||
router.replace('/home') | ||
} | ||
|
||
if (username) { | ||
setForm({ | ||
...form, | ||
username | ||
}) | ||
} | ||
}, []) | ||
|
||
const submit = () => { | ||
|
||
setIsLoading(true) | ||
|
||
fetch(`${API_URL}/auth/login`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(form) | ||
}).then(res => res.json()) | ||
.then(data => { | ||
setIsLoading(false) | ||
|
||
if (data.token) { | ||
setIsLoggedIn(true) | ||
setState({ | ||
token: data.token, | ||
}) | ||
setMessage('') | ||
router.replace('/home') | ||
} else { | ||
setMessage(`${data.message}! ${data.details}`) | ||
setForm({ | ||
...form, | ||
password: '' | ||
}) | ||
} | ||
}) | ||
.catch(err => { | ||
console.log(err) | ||
setIsLoading(false) | ||
Alert.alert('Internal Server Error. Try again later') | ||
setForm({ | ||
username: '', | ||
password: '' | ||
}) | ||
}) | ||
} | ||
|
||
return ( | ||
<KeyboardAvoidingView | ||
className='bg-primary h-full bg-slate-100' | ||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} | ||
> | ||
<ScrollView> | ||
<View className='w-full justify-center min-h-[85vh] px-8 my-6'> | ||
<Text className='text-2xl text-red mt-10 font-psemibold'>Log in to MedShop</Text> | ||
<Text className='text-lg text-red text-center font-bold -mb-5 mt-2'>{message}</Text> | ||
<FormField | ||
title='Username' | ||
value={form.username} | ||
handleChangeText={e => setForm({...form, username: e})} | ||
otherStyles='mt-7' | ||
/> | ||
<FormField | ||
title='Password' | ||
value={form.password} | ||
handleChangeText={e => setForm({...form, password: e})} | ||
otherStyles='mt-7' | ||
/> | ||
<CustomButton | ||
title='Sign In' | ||
handlePress={submit} | ||
containerStyles='mt-7' | ||
isLoading={isSubmitting} | ||
/> | ||
<View className='justify-center pt-5 flex-row gap-2'> | ||
<Text className='text-lg text-red font-pregular'> | ||
Don't have an account? | ||
</Text> | ||
<Link href='/sign-up' className='text-lg font-bold text-secondary'> | ||
Sign Up | ||
</Link> | ||
</View> | ||
</View> | ||
</ScrollView> | ||
{isLoading && ( | ||
<View className="absolute inset-0 bg-slate-700/50 flex justify-center items-center"> | ||
<ActivityIndicator size="large" color="#ffffff" /> | ||
</View> | ||
)} | ||
</KeyboardAvoidingView> | ||
) | ||
} | ||
|
||
export default SignIn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { View, Text, ScrollView, ActivityIndicator, KeyboardAvoidingView, Platform } from 'react-native' | ||
import React, { useState, useEffect } from 'react' | ||
import { SafeAreaView } from 'react-native-safe-area-context' | ||
|
||
import FormField from '../../components/FormField' | ||
import CustomButton from '../../components/CustomButton' | ||
import { useGlobalContext } from '../../context/GlobalProvider' | ||
import { Link, router } from 'expo-router' | ||
import { API_URL } from '../_layout' | ||
|
||
const SignUp = () => { | ||
const [form, setForm] = useState({ | ||
username: '', | ||
email: '', | ||
password: '' | ||
}) | ||
|
||
const [isSubmitting, setisSubmitting] = useState(false) | ||
|
||
const [message, setMessage] = useState('') | ||
|
||
const [isLoading, setIsLoading] = useState(false) | ||
|
||
const { isLoggedIn } = useGlobalContext() | ||
|
||
useEffect(() => { | ||
if (isLoggedIn) { | ||
router.replace('/home') | ||
} | ||
}, []) | ||
|
||
const register = () => { | ||
|
||
setIsLoading(true) | ||
|
||
fetch(`${API_URL}/auth/register`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(form) | ||
}).then(res => res.json()) | ||
.then(data => { | ||
setIsLoading(false) | ||
|
||
if (data.message == 'Registration successful') { | ||
alert('Account created successfully! You can now sign in') | ||
router.replace(`/sign-in?username=${form.username}`) | ||
} else { | ||
setMessage(`${data.message}! ${data.details}`) | ||
setForm({ | ||
...form, | ||
password: '' | ||
}) | ||
} | ||
}) | ||
.catch(err => { | ||
console.log(err) | ||
setIsLoading(false) | ||
Alert.alert('Internal Server Error. Try again later') | ||
setForm({ | ||
username: '', | ||
email: '', | ||
password: '' | ||
}) | ||
}) | ||
} | ||
|
||
return ( | ||
<KeyboardAvoidingView | ||
className='bg-primary h-full bg-slate-100' | ||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} | ||
> | ||
<ScrollView> | ||
<View className='w-full justify-center min-h-[85vh] px-8 my-6'> | ||
<Text className='text-2xl text-red mt-10 font-psemibold'>Register to MedShop</Text> | ||
<Text className='text-lg text-red text-center font-bold -mb-5 mt-2'>{message}</Text> | ||
<FormField | ||
title='Username' | ||
value={form.username} | ||
handleChangeText={e => setForm({...form, username: e})} | ||
otherStyles='mt-7' | ||
/> | ||
<FormField | ||
title='Email' | ||
value={form.email} | ||
handleChangeText={e => setForm({...form, email: e})} | ||
otherStyles='mt-7' | ||
keyboardType='email-address' | ||
/> | ||
<FormField | ||
title='Password' | ||
value={form.password} | ||
handleChangeText={e => setForm({...form, password: e})} | ||
otherStyles='mt-7' | ||
/> | ||
<CustomButton | ||
title='Sign Up' | ||
handlePress={register} | ||
containerStyles='mt-7' | ||
isLoading={isSubmitting} | ||
/> | ||
<View className='justify-center pt-5 flex-row gap-2'> | ||
<Text className='text-lg text-red font-pregular'> | ||
Already have an account? | ||
</Text> | ||
<Link href='/sign-in' className='text-lg font-bold text-secondary'> | ||
Sign In | ||
</Link> | ||
</View> | ||
</View> | ||
</ScrollView> | ||
{isLoading && ( | ||
<View className="absolute inset-0 bg-slate-700/50 flex justify-center items-center"> | ||
<ActivityIndicator size="large" color="#ffffff" /> | ||
</View> | ||
)} | ||
</KeyboardAvoidingView> | ||
) | ||
} | ||
|
||
export default SignUp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { View, Text } from 'react-native' | ||
import React from 'react' | ||
import { Stack } from 'expo-router' | ||
|
||
const ProductsLayout = () => { | ||
return ( | ||
<Stack> | ||
<Stack.Screen | ||
name='home' | ||
options={{ | ||
headerShown: false | ||
}} | ||
/> | ||
<Stack.Screen | ||
name='product-details' | ||
options={{ | ||
headerStyle: { | ||
backgroundColor: '#f1f5f9', | ||
}, | ||
headerBackTitle: 'All products', | ||
headerTintColor: '#d72638', | ||
headerTitle: '', | ||
headerShadowVisible: false, | ||
}} | ||
/> | ||
</Stack> | ||
) | ||
} | ||
|
||
export default ProductsLayout |
Oops, something went wrong.