Unifies naming conventions for users, companies, and rides across backend and mobile app, standardizing field names for consistency and easier data interchange. Introduces endpoints to fetch all companies and rides for sync. Enhances sync logic to support both upload and download of companies, including first-time population from server. Updates local database schema and access logic to match backend structure, improving maintainability and reliability of sync.
156 lines
3.7 KiB
TypeScript
156 lines
3.7 KiB
TypeScript
import { useRouter } from "expo-router";
|
|
import React, { createContext, useContext, useEffect, useState } from "react";
|
|
import {
|
|
deleteSetting,
|
|
getSetting,
|
|
initDB,
|
|
salvarUsuario,
|
|
setSetting,
|
|
} from "@/services/db";
|
|
import { getUserIdFromToken } from "@/utils/jwt";
|
|
|
|
type User = {
|
|
id: string;
|
|
email: string;
|
|
name: string;
|
|
};
|
|
|
|
type AuthContextType = {
|
|
user: User | null;
|
|
token: string | null;
|
|
isLoading: boolean;
|
|
login: (
|
|
email: string,
|
|
password: string,
|
|
token: string,
|
|
user: User,
|
|
) => Promise<void>;
|
|
signup: (
|
|
name: string,
|
|
email: string,
|
|
userId: string,
|
|
token: string,
|
|
) => Promise<void>;
|
|
logout: () => Promise<void>;
|
|
isSignedIn: boolean;
|
|
};
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [token, setToken] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const router = useRouter();
|
|
|
|
useEffect(() => {
|
|
bootstrapAsync();
|
|
}, []);
|
|
|
|
const bootstrapAsync = async () => {
|
|
try {
|
|
await initDB();
|
|
const storedToken = await getSetting("authToken");
|
|
const storedUser = await getSetting("user");
|
|
|
|
if (storedToken && storedUser) {
|
|
let parsedUser: User = JSON.parse(storedUser);
|
|
const realId = getUserIdFromToken(storedToken);
|
|
|
|
if (realId && realId !== parsedUser.id) {
|
|
await salvarUsuario({
|
|
id: realId,
|
|
email: parsedUser.email,
|
|
name: parsedUser.name,
|
|
token: storedToken,
|
|
});
|
|
parsedUser = { ...parsedUser, id: realId };
|
|
await setSetting("user", JSON.stringify(parsedUser));
|
|
}
|
|
|
|
setToken(storedToken);
|
|
setUser(parsedUser);
|
|
router.replace("/home");
|
|
} else {
|
|
setToken(null);
|
|
setUser(null);
|
|
router.replace("/");
|
|
}
|
|
} catch (e) {
|
|
console.error("Failed to restore token", e);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const authContext: AuthContextType = {
|
|
user,
|
|
token,
|
|
isLoading,
|
|
isSignedIn: token !== null,
|
|
login: async (
|
|
_email: string,
|
|
_password: string,
|
|
authToken: string,
|
|
authUser: User,
|
|
) => {
|
|
try {
|
|
setToken(authToken);
|
|
setUser(authUser);
|
|
await setSetting("authToken", authToken);
|
|
await setSetting("user", JSON.stringify(authUser));
|
|
router.replace("/home");
|
|
} catch (error) {
|
|
console.error("Login failed:", error);
|
|
throw error;
|
|
}
|
|
},
|
|
signup: async (
|
|
name: string,
|
|
email: string,
|
|
userId: string,
|
|
authToken: string,
|
|
) => {
|
|
try {
|
|
const newUser: User = {
|
|
id: userId,
|
|
email,
|
|
name,
|
|
};
|
|
|
|
setToken(authToken);
|
|
setUser(newUser);
|
|
await setSetting("authToken", authToken);
|
|
await setSetting("user", JSON.stringify(newUser));
|
|
router.replace("/home");
|
|
} catch (error) {
|
|
console.error("Signup failed:", error);
|
|
throw error;
|
|
}
|
|
},
|
|
logout: async () => {
|
|
try {
|
|
await deleteSetting("authToken");
|
|
await deleteSetting("user");
|
|
setToken(null);
|
|
setUser(null);
|
|
router.replace("/");
|
|
} catch (error) {
|
|
console.error("Logout failed:", error);
|
|
throw error;
|
|
}
|
|
},
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={authContext}>{children}</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext);
|
|
if (!context) {
|
|
throw new Error("useAuth must be used within an AuthProvider");
|
|
}
|
|
return context;
|
|
}
|