mobileapp / src /hooks /useCurrentUser.ts
Antaram Dev Bot
feat: complete ANTARAM.ORG ride-sharing app frontend
5c876be
import { useState, useEffect, useCallback } from 'react';
import { eq } from 'drizzle-orm';
import { useDatabase } from './useDatabase';
import { currentUser } from '../db/schema';
// ─── Types ─────────────────────────────────────────────────────────────────────
interface CurrentUserData {
id: string;
phone: string;
fullName: string;
email: string | null;
avatarUrl: string | null;
gender: 'male' | 'female' | 'other' | null;
homeAddress: string | null;
workAddress: string | null;
preferredLanguage: string | null;
rating: number | null;
totalRides: number | null;
verified: boolean | null;
createdAt: string | null;
updatedAt: string | null;
}
interface UseCurrentUserReturn {
user: CurrentUserData | null;
loading: boolean;
refresh: () => Promise<void>;
updateField: (field: string, value: unknown) => Promise<void>;
updateRole: (role: 'rider' | 'driver') => Promise<void>;
toggleOnline: () => Promise<void>;
updateProfile: (data: Partial<Omit<CurrentUserData, 'id' | 'createdAt'>>) => Promise<void>;
setDarkMode: (isDark: boolean) => Promise<void>;
setNotificationsOn: (enabled: boolean) => Promise<void>;
}
// ─── Hook ──────────────────────────────────────────────────────────────────────
export function useCurrentUser(): UseCurrentUserReturn {
const { db } = useDatabase();
const [user, setUser] = useState<CurrentUserData | null>(null);
const [loading, setLoading] = useState(true);
// ── Load user ────────────────────────────────────────────────────────────────
const loadUser = useCallback(async () => {
try {
setLoading(true);
const rows = await db.select().from(currentUser).limit(1).all();
if (rows.length > 0) {
setUser(rows[0] as CurrentUserData);
} else {
setUser(null);
}
} catch (error) {
console.error('[useCurrentUser] Failed to load user:', error);
setUser(null);
} finally {
setLoading(false);
}
}, [db]);
useEffect(() => {
loadUser();
}, [loadUser]);
// ── Generic field update ─────────────────────────────────────────────────────
const updateField = useCallback(
async (field: string, value: unknown) => {
if (!user) return;
try {
await db
.update(currentUser)
.set({ [field]: value, updatedAt: new Date().toISOString() } as never)
.where(eq(currentUser.id, user.id))
.run();
await loadUser();
} catch (error) {
console.error(`[useCurrentUser] Failed to update ${field}:`, error);
}
},
[db, user, loadUser],
);
// ── Update role (stored in appState or custom column) ────────────────────────
const updateRole = useCallback(
async (_role: 'rider' | 'driver') => {
// Role can be stored in app_state or extended current_user table
// For now we update a field on current_user if the column exists
await updateField('role', _role);
},
[updateField],
);
// ── Toggle online status ─────────────────────────────────────────────────────
const toggleOnline = useCallback(async () => {
await updateField('online', !user?.online);
}, [updateField, user]);
// ── Bulk profile update ──────────────────────────────────────────────────────
const updateProfile = useCallback(
async (
data: Partial<Omit<CurrentUserData, 'id' | 'createdAt'>>,
) => {
if (!user) return;
try {
await db
.update(currentUser)
.set({
...data,
updatedAt: new Date().toISOString(),
} as never)
.where(eq(currentUser.id, user.id))
.run();
await loadUser();
} catch (error) {
console.error('[useCurrentUser] Failed to update profile:', error);
}
},
[db, user, loadUser],
);
// ── Dark mode preference ─────────────────────────────────────────────────────
const setDarkMode = useCallback(
async (isDark: boolean) => {
await updateField('darkMode', isDark);
},
[updateField],
);
// ── Notifications preference ─────────────────────────────────────────────────
const setNotificationsOn = useCallback(
async (enabled: boolean) => {
await updateField('notificationsOn', enabled);
},
[updateField],
);
return {
user,
loading,
refresh: loadUser,
updateField,
updateRole,
toggleOnline,
updateProfile,
setDarkMode,
setNotificationsOn,
};
}