diff --git a/expo/app/(tabs)/_layout.tsx b/expo/app/(tabs)/_layout.tsx
index f87a6224..ca36be34 100644
--- a/expo/app/(tabs)/_layout.tsx
+++ b/expo/app/(tabs)/_layout.tsx
@@ -1,17 +1,19 @@
-import { Redirect, Tabs } from "expo-router";
+import { Redirect, Tabs, useRouter } from "expo-router";
import * as WebBrowser from "expo-web-browser";
import HouseLine from "phosphor-react-native/src/icons/HouseLine";
import MusicNote from "phosphor-react-native/src/icons/MusicNote";
import User from "phosphor-react-native/src/icons/User";
import Users from "phosphor-react-native/src/icons/Users";
+import { useEffect, useState } from "react";
import { HomeTabHeader } from ".";
import ApplicationLoadingScreen from "../../components/ApplicationLoadingScreen";
import { Text } from "../../components/Tamed";
-import { View } from "../../components/Themed";
import FriendHeader from "../../components/headers/FriendHeader";
import Colors from "../../constants/Colors";
+import { supabase } from "../../lib/supabase";
import { useSupabaseUserHook } from "../../lib/useSupabaseUser";
+import { useUserFullProfile } from "../../lib/userProfile";
WebBrowser.maybeCompleteAuthSession();
@@ -38,6 +40,37 @@ export default function TabLayout() {
WebBrowser.maybeCompleteAuthSession();
const user = useSupabaseUserHook();
+ const router = useRouter();
+
+ const profile = useUserFullProfile();
+
+ const [usernameIsFine, setUsernameIsFine] = useState(true);
+
+ useEffect(() => {
+ if (!profile) return;
+ setUsernameIsFine(!!profile?.username);
+ }, [profile]);
+
+ /**
+ * If the user is logged in, we check if the user has a username
+ * If the user not have a username, we re-fetch the user profile to check if he not comming from the ask-name page
+ */
+ useEffect(() => {
+ if (!user) return;
+ if (usernameIsFine) return;
+
+ supabase
+ .from("user_profile")
+ .select("username")
+ .eq("account_id", user.id)
+ .single()
+ .then(({ data }) => {
+ if (data?.username) {
+ return setUsernameIsFine(true);
+ }
+ router.push("/ask-name/");
+ });
+ }, [usernameIsFine]);
if (user === undefined) return ;
diff --git a/expo/app/(tabs)/friends.tsx b/expo/app/(tabs)/friends.tsx
index a06b57d1..752eb5cc 100644
--- a/expo/app/(tabs)/friends.tsx
+++ b/expo/app/(tabs)/friends.tsx
@@ -1,31 +1,7 @@
-import Hammer from "phosphor-react-native/src/icons/Hammer";
import React from "react";
-import { View } from "react-native";
-import { Text } from "../../components/Themed";
+import InDeveloppement from "../../components/InDeveloppement";
export default function TabsFriends() {
- return (
-
-
-
- Cette page est en cours de développement. Merci de revenir plus tard.
-
-
- );
+ return ;
}
diff --git a/expo/app/(tabs)/profile/account/_layout.tsx b/expo/app/(tabs)/profile/account/_layout.tsx
index cd529f97..1f05b836 100644
--- a/expo/app/(tabs)/profile/account/_layout.tsx
+++ b/expo/app/(tabs)/profile/account/_layout.tsx
@@ -2,12 +2,19 @@ import { Stack } from "expo-router";
import ErrorBoundary from "../../../../components/ErrorBoundary";
import ProfileErrorBoundary from "../../../../components/ErrorComponent/ProfileError";
+import { AccountHeader } from "../../../../components/headers/AccountHeader";
export default function AccountLayout() {
return (
}>
-
+ ,
+ }}
+ />
+
+
+
);
diff --git a/expo/app/(tabs)/profile/account/edit.tsx b/expo/app/(tabs)/profile/account/edit.tsx
index 0b428d7d..70b4ef44 100644
--- a/expo/app/(tabs)/profile/account/edit.tsx
+++ b/expo/app/(tabs)/profile/account/edit.tsx
@@ -9,18 +9,23 @@ import ErrorBoundary from "../../../../components/ErrorBoundary";
import { View } from "../../../../components/Themed";
import Warning from "../../../../components/Warning";
import AvatarForm from "../../../../components/profile/AvatarForm";
+import {
+ displayNameRules,
+ emailRules,
+ usernameRules,
+} from "../../../../constants/InputRules";
import {
AuthErrorMessage,
SupabaseErrorCode,
} from "../../../../constants/SupabaseErrorCode";
-import { emailRules, usernameRules } from "../../../../lib/inputRestriction";
import { supabase } from "../../../../lib/supabase";
import { useSupabaseUserHook } from "../../../../lib/useSupabaseUser";
-import { getUserProfile } from "../../../../lib/userProfile";
+import { useUserFullProfile } from "../../../../lib/userProfile";
type EditForm = {
email: string;
username: string;
+ displayName: string;
};
export default function PersonalInfo() {
@@ -34,12 +39,17 @@ export default function PersonalInfo() {
const scrollViewRef = useRef(null);
const [initialUsername, setInitialUsername] = useState(null);
+ const [initialDisplayName, setInitialDisplayname] = useState(
+ null
+ );
const [profilePictureChanged, setProfilePictureChanged] =
useState(false);
const [submittable, setSubmittable] = useState(false);
const [successMessage, setSuccessMessage] = useState(null);
const [emailDisabled, setEmailDisabled] = useState(false);
+ const profile = useUserFullProfile();
+
const {
control,
handleSubmit,
@@ -51,28 +61,43 @@ export default function PersonalInfo() {
defaultValues: {
email: "",
username: "",
+ displayName: "",
},
shouldFocusError: true,
});
const inputsChange = watch();
+
useEffect(() => {
if (user && user.email) {
if (user.app_metadata.provider !== "email") setEmailDisabled(true);
setValue("email", user.email);
- getUserProfile(user.id).then((profile) => {
- if (profile && profile.username) {
- setValue("username", profile.username);
- setInitialUsername(profile.username);
- }
- });
}
}, [user]);
+ useEffect(() => {
+ if (!profile) return;
+
+ if (!profile.profile || !profile.username) {
+ return setError("root", {
+ message: "Impossible de récupérer vos données",
+ });
+ }
+ const displayName: string = profile.profile.nickname;
+ setValue("displayName", displayName);
+ setInitialDisplayname(displayName);
+
+ const username: string = profile.username;
+ setValue("username", username);
+ setInitialUsername(username);
+ }, [profile]);
+
useEffect(() => {
if (inputsChange.email !== user?.email) return setSubmittable(true);
if (inputsChange.username !== initialUsername) return setSubmittable(true);
if (profilePictureChanged) return setSubmittable(true);
+ if (inputsChange.displayName !== initialDisplayName)
+ return setSubmittable(true);
setSubmittable(false);
}, [inputsChange]);
@@ -130,7 +155,40 @@ export default function PersonalInfo() {
return "Pseudo mis à jour";
};
- const onSubmit = async ({ email, username }: EditForm) => {
+ /**
+ * Update display name
+ * @param displayName
+ * @returns string if success, undefined if error
+ */
+ const updateDisplayName = async (
+ displayName: string
+ ): Promise => {
+ if (!profile || !profile.profile?.id) return;
+ const { error } = await supabase
+ .from("profile")
+ .update({
+ nickname: inputsChange.displayName,
+ })
+ .eq("id", profile.profile?.id);
+
+ if (error) {
+ setError("displayName", {
+ message: "Impossible de mettre à jour le nom d'affichage",
+ });
+ return;
+ }
+ setInitialDisplayname(displayName);
+ setValue("displayName", displayName);
+
+ return "Nom public";
+ };
+
+ /**
+ * Possible to upgrade with parallel requests
+ * @param inputs
+ * @returns
+ */
+ const onSubmit = async ({ email, username, displayName }: EditForm) => {
const validationResum: string[] = [];
if (inputsChange.email !== user?.email) {
@@ -143,6 +201,11 @@ export default function PersonalInfo() {
if (res) validationResum.push(res);
}
+ if (inputsChange.displayName !== initialDisplayName) {
+ const res = await updateDisplayName(displayName);
+ if (res) validationResum.push(res);
+ }
+
if (profilePictureChanged) {
if (!avatarRef.current) return;
setProfilePictureChanged(false);
@@ -193,6 +256,15 @@ export default function PersonalInfo() {
placeholder="@nouveau_nom"
rules={usernameRules}
errorMessage={errors.username && errors.username.message}
+ info="Le nom d'utilisateur doit être unique"
+ />
+
Alert.alert("Not implemented")}
+ disabled
>
Supprimer mon compte
diff --git a/expo/app/(tabs)/profile/account/help.tsx b/expo/app/(tabs)/profile/account/help.tsx
new file mode 100644
index 00000000..a8aef717
--- /dev/null
+++ b/expo/app/(tabs)/profile/account/help.tsx
@@ -0,0 +1,5 @@
+import InDeveloppement from "../../../../components/InDeveloppement";
+
+export default function Help() {
+ return ;
+}
diff --git a/expo/app/(tabs)/profile/account/index.tsx b/expo/app/(tabs)/profile/account/index.tsx
index e84efdb2..79329cb2 100644
--- a/expo/app/(tabs)/profile/account/index.tsx
+++ b/expo/app/(tabs)/profile/account/index.tsx
@@ -22,13 +22,13 @@ export default function Account() {
}
title="Sécurité"
- href="/account/security"
+ href="/(tabs)/profile/account/security"
/>
}
title="Notifications"
- href="/manage-account/notifications"
+ href="/(tabs)/profile/account/notifications"
/>
}
title="Assistance"
- href="/manage-account/help"
+ href="/(tabs)/profile/account/help"
/>
+
);
}
diff --git a/expo/app/(tabs)/profile/account/notifications.tsx b/expo/app/(tabs)/profile/account/notifications.tsx
new file mode 100644
index 00000000..ad580350
--- /dev/null
+++ b/expo/app/(tabs)/profile/account/notifications.tsx
@@ -0,0 +1,5 @@
+import InDeveloppement from "../../../../components/InDeveloppement";
+
+export default function Notifications() {
+ return ;
+}
diff --git a/expo/app/(tabs)/profile/account/security.tsx b/expo/app/(tabs)/profile/account/security.tsx
new file mode 100644
index 00000000..c786afa5
--- /dev/null
+++ b/expo/app/(tabs)/profile/account/security.tsx
@@ -0,0 +1,5 @@
+import InDeveloppement from "../../../../components/InDeveloppement";
+
+export default function Security() {
+ return ;
+}
diff --git a/expo/app/(tabs)/rooms/[id]/_layout.tsx b/expo/app/(tabs)/rooms/[id]/_layout.tsx
index 849904d9..03949da5 100644
--- a/expo/app/(tabs)/rooms/[id]/_layout.tsx
+++ b/expo/app/(tabs)/rooms/[id]/_layout.tsx
@@ -1,4 +1,4 @@
-import { Stack, useLocalSearchParams } from "expo-router";
+import { Stack, router, useLocalSearchParams } from "expo-router";
import {
ReactNode,
createContext,
@@ -8,6 +8,7 @@ import {
} from "react";
import { Socket } from "socket.io-client";
+import Alert from "../../../../components/Alert";
import ErrorBoundary from "../../../../components/ErrorBoundary";
import RoomErrorBoundary from "../../../../components/ErrorComponent/RoomError";
import WebsocketError from "../../../../components/ErrorComponent/WebsocketError";
@@ -54,6 +55,13 @@ const WebSocketProvider = ({
setSocketError(null);
});
+ socketInstance.on("room:end", () => {
+ Alert.alert(
+ "Fermeture de la salle, redirection vers la liste des salles"
+ );
+ router.push("/rooms");
+ });
+
return () => {
socketInstance.disconnect();
};
diff --git a/expo/app/(tabs)/rooms/_layout.tsx b/expo/app/(tabs)/rooms/_layout.tsx
index d45c1b9b..78f5ff00 100644
--- a/expo/app/(tabs)/rooms/_layout.tsx
+++ b/expo/app/(tabs)/rooms/_layout.tsx
@@ -1,9 +1,11 @@
import { Stack } from "expo-router";
+import RoomsHeader from "../../../components/headers/RoomsHeader";
+
export default function RoomsTabLayout() {
return (
-
+ }} />
- Salles d'écoute
-
-
-
-
);
@@ -29,7 +18,4 @@ const styles = StyleSheet.create({
marginVertical: 21,
gap: 36,
},
- buttonContainer: {
- gap: 8,
- },
});
diff --git a/expo/app/_layout.tsx b/expo/app/_layout.tsx
index 4737980f..0dd42562 100644
--- a/expo/app/_layout.tsx
+++ b/expo/app/_layout.tsx
@@ -7,6 +7,7 @@ import { MenuProvider } from "react-native-popup-menu";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { Text, View } from "../components/Themed";
+import { AccountHeader } from "../components/headers/AccountHeader";
import Colors from "../constants/Colors";
import { supabase } from "../lib/supabase";
@@ -97,7 +98,7 @@ function RootLayoutNav() {
}}
/>
diff --git a/expo/app/ask-name.tsx b/expo/app/ask-name.tsx
index 465a9bc4..e55960b1 100644
--- a/expo/app/ask-name.tsx
+++ b/expo/app/ask-name.tsx
@@ -1,91 +1,97 @@
-import { router } from "expo-router";
-import { useState } from "react";
-import { StyleSheet, Text, TextInput, View } from "react-native";
+import { useRouter } from "expo-router";
+import { useForm } from "react-hook-form";
import { Screen } from "react-native-screens";
-import Alert from "../components/Alert";
import Button from "../components/Button";
+import ControlledInput from "../components/ControlledInput";
+import { Text } from "../components/Themed";
+import Font from "../constants/Font";
+import { usernameRules } from "../constants/InputRules";
import { SupabaseErrorCode } from "../constants/SupabaseErrorCode";
import { supabase } from "../lib/supabase";
-import useSupabaseUser from "../lib/useSupabaseUser";
+import { useSupabaseUserHook } from "../lib/useSupabaseUser";
+
+type UsernameForm = {
+ username: string;
+};
export default function AskName() {
- const [username, setUsername] = useState("");
+ const user = useSupabaseUserHook();
+ const router = useRouter();
- const handleSubmitUsername = async () => {
- const user = await useSupabaseUser();
- if (!user?.id) return;
+ const {
+ control,
+ handleSubmit,
+ setError,
+ formState: { errors },
+ } = useForm({
+ defaultValues: {
+ username: "",
+ },
+ shouldFocusError: true,
+ });
- if (username.length < 5) {
- Alert.alert("Le pseudo doit faire au moins 5 caractères");
- return;
- }
+ /**
+ * Possible to upgrade with parallel requests
+ * @param inputs
+ * @returns
+ */
+ const onSubmit = async ({ username }: UsernameForm) => {
+ console.log("submitting", username);
+ console.log("profile", user);
+ if (!user) return;
+
+ console.log("submitting", username);
const { error } = await supabase
.from("user_profile")
.update({ username })
- .eq("account_id", user?.id);
- if (error) {
- if (error.code === SupabaseErrorCode.CONSTRAINT_VIOLATION) {
- Alert.alert("Attention, Ce pseudo est déjà pris");
- return;
- }
- Alert.alert("Erreur, Une erreur est survenue");
+ .eq("account_id", user.id);
+
+ if (!error) {
+ router.push("/");
+ }
+ if (error?.code === SupabaseErrorCode.CONSTRAINT_VIOLATION) {
+ setError("username", {
+ type: "manual",
+ message: "Ce nom d'utilisateur est déjà pris",
+ });
}
- router.replace("/(tabs)");
};
return (
-
-
- Choisi ton pseudo
-
-
-
-
-
+
+
+ Ici, tu peux choisir un nom d'utilisateur pour que tes amis puissent te
+ trouver plus facilement. Ce nom est unique sur DATSMYSONG !
+
+
+
);
}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- // justifyContent: "center",
- alignItems: "center",
- gap: 20,
- width: "100%",
- },
- form: {
- padding: 20,
- alignItems: "center",
- gap: 30,
- },
- buttonContainer: {
- alignItems: "center",
- },
- title: {
- fontSize: 30,
- fontWeight: "bold",
- textAlign: "center",
- },
- titleContainer: {
- marginTop: 100,
- marginBottom: 100,
- },
- containerWithDivider: {
- flexDirection: "row",
- alignItems: "center",
- justifyContent: "center",
- },
-});
diff --git a/expo/app/auth/login.tsx b/expo/app/auth/login.tsx
index 40cab5b2..613d166f 100644
--- a/expo/app/auth/login.tsx
+++ b/expo/app/auth/login.tsx
@@ -6,8 +6,8 @@ import { StyleSheet, View } from "react-native";
import Button from "../../components/Button";
import ControlledInput from "../../components/ControlledInput";
import Alert from "../../components/Warning";
+import { emailRules } from "../../constants/InputRules";
import { AuthErrorMessage } from "../../constants/SupabaseErrorCode";
-import { emailRules } from "../../lib/inputRestriction";
import { supabase } from "../../lib/supabase";
type LoginForm = {
diff --git a/expo/app/auth/register.tsx b/expo/app/auth/register.tsx
index 395f6070..e340993e 100644
--- a/expo/app/auth/register.tsx
+++ b/expo/app/auth/register.tsx
@@ -5,12 +5,12 @@ import { ScrollView, StyleSheet, Text, View } from "react-native";
import Alert from "../../components/Alert";
import Button from "../../components/Button";
import ControlledInput from "../../components/ControlledInput";
-import { getApiUrl } from "../../lib/apiUrl";
import {
emailRules,
passwordRules,
usernameRules,
-} from "../../lib/inputRestriction";
+} from "../../constants/InputRules";
+import { getApiUrl } from "../../lib/apiUrl";
type FormData = {
username: string;
diff --git a/expo/components/ControlledInput.tsx b/expo/components/ControlledInput.tsx
index 96ab5d36..bf701a24 100644
--- a/expo/components/ControlledInput.tsx
+++ b/expo/components/ControlledInput.tsx
@@ -3,6 +3,7 @@ import { StyleSheet, Text, TextInputProps, View } from "react-native";
import CustomPasswordInput from "./CustomPasswordInput";
import CustomTextInput, { CustomTextInputProps } from "./CustomTextInput";
+import Subtitle from "./text/Subtitle";
interface ControlledInputProps extends CustomTextInputProps {
control: any;
@@ -14,6 +15,7 @@ interface ControlledInputProps extends CustomTextInputProps {
secureTextEntry?: boolean;
errorMessage?: string | undefined;
onSubmitEditing?: () => void;
+ info?: string;
}
export default function ControlledInput({
@@ -23,6 +25,7 @@ export default function ControlledInput({
rules,
secureTextEntry,
errorMessage,
+ info,
...props
}: ControlledInputProps) {
return (
@@ -57,6 +60,7 @@ export default function ControlledInput({
}
name={name}
/>
+ {info && {info}}
{errorMessage && (
{errorMessage ?? "Le champ est invalide"}
diff --git a/expo/components/InDeveloppement.tsx b/expo/components/InDeveloppement.tsx
new file mode 100644
index 00000000..9a076034
--- /dev/null
+++ b/expo/components/InDeveloppement.tsx
@@ -0,0 +1,31 @@
+import Hammer from "phosphor-react-native/src/icons/Hammer";
+import React from "react";
+import { View } from "react-native";
+
+import { Text } from "./Themed";
+
+export default function InDeveloppement() {
+ return (
+
+
+
+ Cette page est en cours de développement. Merci de revenir plus tard.
+
+
+ );
+}
diff --git a/expo/components/RoomHistory.tsx b/expo/components/RoomHistory.tsx
index edbbd9c0..f5885f18 100644
--- a/expo/components/RoomHistory.tsx
+++ b/expo/components/RoomHistory.tsx
@@ -107,7 +107,7 @@ const RoomHistory: React.FC = ({ roomId }) => {
{participant.profile.nickname}
diff --git a/expo/components/UserRoomHistory.tsx b/expo/components/UserRoomHistory.tsx
index 96ea6df1..f06a62d2 100644
--- a/expo/components/UserRoomHistory.tsx
+++ b/expo/components/UserRoomHistory.tsx
@@ -1,6 +1,6 @@
import { QueryData } from "@supabase/supabase-js/dist/module/lib/types";
import { useEffect, useState } from "react";
-import { FlatList, StyleSheet } from "react-native";
+import { FlatList } from "react-native";
import RoomHistoryInfoCard from "./RoomHistoryInfoCard";
import { View } from "./Themed";
diff --git a/expo/components/headers/AccountHeader.tsx b/expo/components/headers/AccountHeader.tsx
new file mode 100644
index 00000000..6d2188a6
--- /dev/null
+++ b/expo/components/headers/AccountHeader.tsx
@@ -0,0 +1,29 @@
+import { View } from "react-native";
+
+import H1 from "../text/H1";
+
+export const AccountHeader = () => {
+ return (
+
+
+ Gérer mon compte
+
+
+ );
+};
diff --git a/expo/components/headers/RoomsHeader.tsx b/expo/components/headers/RoomsHeader.tsx
new file mode 100644
index 00000000..9259283f
--- /dev/null
+++ b/expo/components/headers/RoomsHeader.tsx
@@ -0,0 +1,33 @@
+import { StyleSheet, View } from "react-native";
+
+import Button from "../Button";
+import H1 from "../text/H1";
+
+export default function RoomsHeader() {
+ return (
+
+ Salles d'écoute
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ headerContainer: {
+ flex: 1,
+ paddingHorizontal: 24,
+ paddingVertical: 21,
+ gap: 36,
+ backgroundColor: "#E6E6E6",
+ },
+ buttonContainer: {
+ gap: 8,
+ },
+});
diff --git a/expo/components/profile/AvatarForm.tsx b/expo/components/profile/AvatarForm.tsx
index ffaa74dc..3f80fc2d 100644
--- a/expo/components/profile/AvatarForm.tsx
+++ b/expo/components/profile/AvatarForm.tsx
@@ -88,12 +88,21 @@ const AvatarForm = forwardRef((props: AvatarProps, ref) => {
return (
Photo de profil
-
+
@@ -71,13 +50,13 @@ export const ProfileHeader = () => {
}}
>
-
+
- {userProfile ? userProfile.username : "chargement"}
+ {profile?.profile ? profile.profile?.nickname : "chargement"}
- @{profile?.nickname}
+ @{profile?.username}
diff --git a/expo/components/profile/SettingsOptions.tsx b/expo/components/profile/SettingsOptions.tsx
index 0f92ede4..29b46dae 100644
--- a/expo/components/profile/SettingsOptions.tsx
+++ b/expo/components/profile/SettingsOptions.tsx
@@ -46,7 +46,6 @@ export default SettingsOptions;
const styles = StyleSheet.create({
container: {
- backgroundColor: "white",
gap: 24,
paddingVertical: 16,
paddingHorizontal: 20,
diff --git a/expo/lib/inputRestriction.ts b/expo/constants/InputRules.ts
similarity index 67%
rename from expo/lib/inputRestriction.ts
rename to expo/constants/InputRules.ts
index 1f0805bb..74704a05 100644
--- a/expo/lib/inputRestriction.ts
+++ b/expo/constants/InputRules.ts
@@ -3,6 +3,7 @@ import { RegisterOptions } from "react-hook-form";
/**
* This file contains all the rules for the inputs with library react-hook-form
*/
+
const usernameRules: RegisterOptions = {
required: "Un nom d'utilisateur est requis",
minLength: {
@@ -13,6 +14,12 @@ const usernameRules: RegisterOptions = {
value: 15,
message: "Le nom d'utilisateur doit contenir au plus 15 caractères",
},
+ // pas d'espace ni de caractères spéciaux
+ pattern: {
+ value: /^[a-zA-Z0-9]*$/,
+ message:
+ "Le nom d'utilisateur ne doit contenir que des lettres et des chiffres",
+ },
};
const emailRules: RegisterOptions = {
@@ -39,4 +46,16 @@ const passwordRules: RegisterOptions = {
},
};
-export { emailRules, passwordRules, usernameRules };
+const displayNameRules: RegisterOptions = {
+ required: "Veuillez saisir votre nom d'affichage",
+ minLength: {
+ value: 3,
+ message: "Le nom d'affichage doit contenir au moins 3 caractères",
+ },
+ maxLength: {
+ value: 15,
+ message: "Le nom d'affichage doit contenir au plus 15 caractères",
+ },
+};
+
+export { emailRules, passwordRules, usernameRules, displayNameRules };
diff --git a/expo/lib/userProfile.ts b/expo/lib/userProfile.ts
index e16771e1..1b38f88b 100644
--- a/expo/lib/userProfile.ts
+++ b/expo/lib/userProfile.ts
@@ -52,6 +52,40 @@ export function useUserProfile() {
return profile;
}
+const fullProfileRequest = supabase
+ .from("user_profile")
+ .select("*, profile(*)")
+ .single();
+
+type FullProfile = QueryData;
+
+export function useUserFullProfile() {
+ const [profile, setProfile] = useState();
+ const user = useSupabaseUserHook();
+
+ useEffect(() => {
+ const fetchProfile = async () => {
+ if (!user) return setProfile(null);
+
+ const { data, error } = await supabase
+ .from("user_profile")
+ .select("*, profile(*)")
+ .eq("account_id", user.id)
+ .single();
+
+ if (error) {
+ return setProfile(null);
+ }
+
+ setProfile(data);
+ };
+
+ fetchProfile();
+ }, [user]);
+
+ return profile;
+}
+
export const getUsernameFromUser = async (
user: User
): Promise<{