Improve flow
This commit is contained in:
parent
2bfe51017f
commit
03a25dace3
4 changed files with 63 additions and 29 deletions
|
|
@ -58,6 +58,7 @@ export const getBookingRouter = () => {
|
|||
return c.json({ error: "owner_id is incorrect" }, 400);
|
||||
}
|
||||
|
||||
let hasCreatedAccount = false;
|
||||
if (!maybeUser) {
|
||||
// Check if email already exists in the database
|
||||
const { data: existingUser, error: existingUserError } = await supabase
|
||||
|
|
@ -72,6 +73,7 @@ export const getBookingRouter = () => {
|
|||
}
|
||||
|
||||
if (!existingUser) {
|
||||
hasCreatedAccount = true;
|
||||
// Create a temporary user for the booking
|
||||
const result = await createInvitedUser(
|
||||
supabase,
|
||||
|
|
@ -181,7 +183,7 @@ export const getBookingRouter = () => {
|
|||
}
|
||||
|
||||
// Grant access to the current user (invited user) as a non-admin member
|
||||
const { error: tabloAccessError } = await supabase.from("tablo_access").insert(
|
||||
const { error: tabloAccessError } = await supabase.from("tablo_access").upsert(
|
||||
{
|
||||
tablo_id: tabloData.id,
|
||||
user_id: bookerUserDataTyped.id,
|
||||
|
|
@ -190,10 +192,10 @@ export const getBookingRouter = () => {
|
|||
// -------------
|
||||
is_active: true,
|
||||
granted_by: ownerId,
|
||||
},
|
||||
{
|
||||
onConflict: "tablo_id, user_id",
|
||||
}
|
||||
// {
|
||||
// onConflict: "tablo_id, user_id",
|
||||
// }
|
||||
);
|
||||
|
||||
if (tabloAccessError) {
|
||||
|
|
@ -275,7 +277,12 @@ export const getBookingRouter = () => {
|
|||
`,
|
||||
});
|
||||
|
||||
return c.json({ id: tabloData.id });
|
||||
return c.json({
|
||||
message: "Booking successful",
|
||||
tablo_id: tabloData.id,
|
||||
hasCreatedAccount,
|
||||
email: bookerUserDataTyped.email,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation } from "@tanstack/react-query";
|
||||
import { toast, useSession } from "@xtablo/shared";
|
||||
import { invalidatePublicSlots, queryClient, toast, useSession } from "@xtablo/shared";
|
||||
import { api } from "../lib/api";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
type BookSlotPayload = {
|
||||
event_type_standard_name: string;
|
||||
|
|
@ -17,9 +18,14 @@ type BookSlotPayload = {
|
|||
};
|
||||
|
||||
// Book a slot with an event type owner
|
||||
export const useBookSlot = (onSuccess?: (data: { id: string }) => void) => {
|
||||
export const useBookSlot = () => {
|
||||
const navigate = useNavigate();
|
||||
const { session } = useSession();
|
||||
return useMutation<{ id: string }, unknown, BookSlotPayload>({
|
||||
return useMutation<
|
||||
{ tablo_id: string; hasCreatedAccount: boolean; email: string },
|
||||
unknown,
|
||||
BookSlotPayload
|
||||
>({
|
||||
mutationFn: async (payload: BookSlotPayload) => {
|
||||
const { data } = await api.post("/api/v1/book/slot", payload, {
|
||||
headers: {
|
||||
|
|
@ -29,7 +35,23 @@ export const useBookSlot = (onSuccess?: (data: { id: string }) => void) => {
|
|||
});
|
||||
return data;
|
||||
},
|
||||
onSuccess,
|
||||
onSuccess: ({ tablo_id, hasCreatedAccount, email }) => {
|
||||
toast.add({
|
||||
title: "Réservation confirmée avec succès",
|
||||
description: hasCreatedAccount
|
||||
? "Vous avez reçu un email de confirmation et votre compte a été créé automatiquement. Un mot de passe vous a été envoyé par email."
|
||||
: "Vous recevrez un email de confirmation dans quelques instants",
|
||||
type: "success",
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["tablos"] });
|
||||
invalidatePublicSlots();
|
||||
if (hasCreatedAccount) {
|
||||
navigate(`/login?email=${email}`, { replace: true });
|
||||
} else {
|
||||
navigate(`/tablos/${tablo_id}`, { replace: true });
|
||||
}
|
||||
// navigate(0);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error);
|
||||
toast.add(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { CustomModal } from "@ui/components/CustomModal";
|
||||
import { useBookSlot } from "../hooks/book";
|
||||
import { useSession } from "@xtablo/shared/contexts/SessionContext";
|
||||
import { useTheme } from "@xtablo/shared/contexts/ThemeContext";
|
||||
import { invalidatePublicSlots, TimeSlot, usePublicSlots } from "@xtablo/shared/hooks/public";
|
||||
import { TimeSlot, usePublicSlots } from "@xtablo/shared/hooks/public";
|
||||
import { Button } from "@xtablo/ui/components/button";
|
||||
import { FieldError } from "@xtablo/ui/components/field";
|
||||
import { Input } from "@xtablo/ui/components/input";
|
||||
|
|
@ -27,7 +26,7 @@ import {
|
|||
UserIcon,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { api } from "../lib/api";
|
||||
|
||||
|
|
@ -36,8 +35,6 @@ export function PublicBookingPage() {
|
|||
user_info: string;
|
||||
event_type_standard_name: string;
|
||||
}>();
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
// const { mutateAsync: signUpWithoutPassword, isPending: isSigningUpWithoutPassword } =
|
||||
// useSignUpWithoutPassword(supabase, api);
|
||||
const { session } = useSession();
|
||||
|
|
@ -51,14 +48,7 @@ export function PublicBookingPage() {
|
|||
event_type_standard_name || ""
|
||||
);
|
||||
|
||||
const { mutateAsync: bookSlot, isPending: isBookingSlot } = useBookSlot(
|
||||
(data: { id: string }) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["tablos"] });
|
||||
invalidatePublicSlots();
|
||||
navigate(`/tablos/${data.id}`, { replace: true });
|
||||
navigate(0);
|
||||
}
|
||||
);
|
||||
const { mutateAsync: bookSlot, isPending: isBookingSlot } = useBookSlot();
|
||||
|
||||
const isPending = isBookingSlot;
|
||||
|
||||
|
|
@ -76,6 +66,7 @@ export function PublicBookingPage() {
|
|||
date: Date;
|
||||
slot: TimeSlot;
|
||||
} | null>(null);
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
email: "",
|
||||
name: "",
|
||||
|
|
@ -88,7 +79,7 @@ export function PublicBookingPage() {
|
|||
// Loading messages rotation
|
||||
const loadingMessages = [
|
||||
"Nous créons votre rendez-vous, veuillez patienter",
|
||||
"Creation de votre compte, ...",
|
||||
"Creation de votre compte...",
|
||||
"Préparation de votre réservation...",
|
||||
"Configuration de votre appel...",
|
||||
"Finalisation de votre créneau...",
|
||||
|
|
@ -246,6 +237,10 @@ export function PublicBookingPage() {
|
|||
};
|
||||
|
||||
const validateForm = () => {
|
||||
if (user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const errors = { email: "", name: "" };
|
||||
let isValid = true;
|
||||
|
||||
|
|
@ -288,6 +283,16 @@ export function PublicBookingPage() {
|
|||
const duration = eventType?.duration || 60; // duration in minutes
|
||||
const endTime = calculateEndTime(startTime, duration);
|
||||
|
||||
const userDetails = user
|
||||
? {
|
||||
name: user.user_metadata.name,
|
||||
email: user.email || "",
|
||||
}
|
||||
: {
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
};
|
||||
|
||||
bookSlot({
|
||||
event_type_standard_name: event_type_standard_name as string,
|
||||
owner_short_id: shortUserId || "",
|
||||
|
|
@ -296,10 +301,7 @@ export function PublicBookingPage() {
|
|||
start_time: selectedSlot?.slot.time || "",
|
||||
end_time: endTime || "",
|
||||
},
|
||||
user_details: {
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
},
|
||||
user_details: userDetails,
|
||||
});
|
||||
|
||||
handleCloseModal();
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ import { Label } from "@xtablo/ui/components/label";
|
|||
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useSearchParams } from "react-router-dom";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useLoginEmail } from "../hooks/auth";
|
||||
|
||||
export function LoginPage() {
|
||||
const [searchParams] = useSearchParams();
|
||||
const emailParam = searchParams.get("email");
|
||||
const { t } = useTranslation(["auth", "common"]);
|
||||
const redirectUrl = localStorage.getItem("redirectUrl");
|
||||
const {
|
||||
|
|
@ -22,8 +24,9 @@ export function LoginPage() {
|
|||
} = useLoginEmail({
|
||||
redirectUrl: redirectUrl ?? null,
|
||||
});
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
email: "",
|
||||
email: emailParam ?? "",
|
||||
password: "",
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue