diff --git a/mobile/app/signup.tsx b/mobile/app/signup.tsx
new file mode 100644
index 0000000..eda2367
--- /dev/null
+++ b/mobile/app/signup.tsx
@@ -0,0 +1,140 @@
+import React from 'react';
+import { StyleSheet, View, Button, Text, TextInput, ActivityIndicator, Alert } from 'react-native';
+import { Formik } from 'formik';
+import * as Yup from 'yup';
+import { useRouter } from 'expo-router';
+
+import authApi from '../services/authApi';
+import { useApi } from '@/services/useAPI';
+
+
+const SignUpSchema = Yup.object().shape({
+ name: Yup.string()
+ .min(2, 'Too Short!')
+ .required('Name is required'),
+ email: Yup.string()
+ .email('Invalid email')
+ .required('Email is required'),
+ password: Yup.string()
+ .min(8, 'Password must be at least 8 characters')
+ .required('Password is required'),
+ confirmPassword: Yup.string()
+ .oneOf([Yup.ref('password')], 'Passwords must match')
+ .required('Confirm Password is required'),
+});
+
+export default function SignUpScreen() {
+ const router = useRouter();
+ const { request: performSignUp, loading, error } = useApi(authApi.signUp);
+
+
+ const handleSubmit = async (values: any) => {
+ const { name, email, password } = values;
+ const result = await performSignUp({ name, email, password });
+
+ if (result.success) {
+ Alert.alert(
+ 'Success!',
+ result.data?.message || 'You have been registered successfully.',
+ [{ text: 'OK', onPress: () => router.replace('/login') }]
+ );
+ }
+
+ };
+
+ return (
+
+ Create Account
+
+
+
+ {({ handleChange, handleBlur, handleSubmit, values, errors, touched }) => (
+
+
+ {errors.name && touched.name ? {errors.name} : null}
+
+
+ {errors.email && touched.email ? {errors.email} : null}
+
+
+ {errors.password && touched.password ? {errors.password} : null}
+
+
+ {errors.confirmPassword && touched.confirmPassword ? {errors.confirmPassword} : null}
+
+
+ {error && {error}}
+
+ {loading ? (
+
+ ) : (
+
+ )}
+
+
+ );
+}
+
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ padding: 20,
+ },
+ title: {
+ fontSize: 28,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ marginBottom: 24,
+ },
+ input: {
+ height: 40,
+ borderColor: 'gray',
+ borderWidth: 1,
+ borderRadius: 5,
+ marginBottom: 10,
+ paddingHorizontal: 10,
+ },
+ errorText: {
+ color: 'red',
+ marginBottom: 10,
+ },
+ button: {
+ marginTop: 10,
+ },
+});
\ No newline at end of file
diff --git a/mobile/services/authApi.ts b/mobile/services/authApi.ts
new file mode 100644
index 0000000..c522685
--- /dev/null
+++ b/mobile/services/authApi.ts
@@ -0,0 +1,23 @@
+import apiClient from './apiClient';
+import { AxiosResponse } from 'axios';
+
+
+interface SignUpPayload {
+ name: string;
+ email: string;
+ password: string;
+}
+
+
+interface SignUpResponse {
+ message: string;
+
+}
+
+const signUp = (payload: SignUpPayload): Promise> => {
+ return apiClient.post('/auth/signup', payload);
+};
+
+export default {
+ signUp,
+};
\ No newline at end of file
diff --git a/mobile/services/useAPI.ts b/mobile/services/useAPI.ts
new file mode 100644
index 0000000..32ac529
--- /dev/null
+++ b/mobile/services/useAPI.ts
@@ -0,0 +1,34 @@
+import { useState } from 'react';
+import { AxiosResponse } from 'axios';
+
+
+type ApiFunc = (...args: P) => Promise>;
+
+export const useApi = (apiFunc: ApiFunc) => {
+ const [data, setData] = useState(null);
+ const [error, setError] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ const request = async (...args: P): Promise<{ success: boolean; data?: T; error?: string }> => {
+ setLoading(true);
+ setError(null);
+ try {
+ const response = await apiFunc(...args);
+ setData(response.data);
+ setLoading(false);
+ return { success: true, data: response.data };
+ } catch (err: any) {
+ const errorMessage = err.response?.data?.message || err.message || 'An unexpected error occurred.';
+ setError(errorMessage);
+ setLoading(false);
+ return { success: false, error: errorMessage };
+ }
+ };
+
+ return {
+ data,
+ error,
+ loading,
+ request,
+ };
+};
\ No newline at end of file