|
| 1 | +"use client" |
| 2 | + |
| 3 | +import React, { useState } from "react" |
| 4 | +import { motion } from "framer-motion" |
| 5 | +import { cn } from "@utils/cn" |
| 6 | +import toast from "react-hot-toast" |
| 7 | +import { useRouter } from "next/navigation" |
| 8 | +import { |
| 9 | + IconBrandWhatsapp, |
| 10 | + IconLoader, |
| 11 | + IconSparkles |
| 12 | +} from "@tabler/icons-react" |
| 13 | +import InteractiveNetworkBackground from "@components/ui/InteractiveNetworkBackground" |
| 14 | + |
| 15 | +const questions = [ |
| 16 | + { |
| 17 | + id: "needs-pa", |
| 18 | + question: |
| 19 | + "Do you often juggle multiple priorities, manage a small team, lead projects, and handle countless day-to-day tasks on your own? Many professionals spend too much time scheduling meetings, organizing their calendar, responding to emails, and doing other administrative work that eats into their day. Do you ever wish you had someone to take these repetitive tasks off your plate?\n\nDo you ever feel the need for a personal assistant?", |
| 20 | + type: "yes-no", |
| 21 | + required: true |
| 22 | + }, |
| 23 | + { |
| 24 | + id: "whatsapp_notifications_number", |
| 25 | + question: |
| 26 | + "To send you important notifications, task updates, and reminders on WhatsApp, please enter your number with the country code.", |
| 27 | + type: "text-input", |
| 28 | + required: true, |
| 29 | + placeholder: "+14155552671", |
| 30 | + icon: <IconBrandWhatsapp /> |
| 31 | + } |
| 32 | +] |
| 33 | + |
| 34 | +const CompleteProfilePage = () => { |
| 35 | + const [answers, setAnswers] = useState({}) |
| 36 | + const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0) |
| 37 | + const [isSubmitting, setIsSubmitting] = useState(false) |
| 38 | + const router = useRouter() |
| 39 | + |
| 40 | + const handleAnswer = (questionId, answer) => { |
| 41 | + setAnswers((prev) => ({ ...prev, [questionId]: answer })) |
| 42 | + } |
| 43 | + |
| 44 | + const handleNext = () => { |
| 45 | + if (currentQuestionIndex < questions.length - 1) { |
| 46 | + setCurrentQuestionIndex((prev) => prev + 1) |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + const handleSubmit = async () => { |
| 51 | + if (!answers["needs-pa"] || !answers["whatsapp_notifications_number"]) { |
| 52 | + toast.error("Please answer all questions to continue.") |
| 53 | + return |
| 54 | + } |
| 55 | + setIsSubmitting(true) |
| 56 | + try { |
| 57 | + const response = await fetch("/api/settings/complete-profile", { |
| 58 | + method: "POST", |
| 59 | + headers: { "Content-Type": "application/json" }, |
| 60 | + body: JSON.stringify(answers) |
| 61 | + }) |
| 62 | + if (!response.ok) { |
| 63 | + const result = await response.json() |
| 64 | + throw new Error(result.detail || "Failed to update profile.") |
| 65 | + } |
| 66 | + toast.success("Thank you! Your profile is now complete.") |
| 67 | + router.push("/chat") |
| 68 | + } catch (error) { |
| 69 | + toast.error(`Error: ${error.message}`) |
| 70 | + } finally { |
| 71 | + setIsSubmitting(false) |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + const currentQuestion = questions[currentQuestionIndex] |
| 76 | + |
| 77 | + return ( |
| 78 | + <div className="relative flex flex-col items-center justify-center min-h-screen w-full p-4 sm:p-8 text-white overflow-hidden"> |
| 79 | + <div className="absolute inset-0 z-[-1]"> |
| 80 | + <InteractiveNetworkBackground /> |
| 81 | + </div> |
| 82 | + <motion.div |
| 83 | + key="complete-profile" |
| 84 | + initial={{ opacity: 0, y: 20 }} |
| 85 | + animate={{ opacity: 1, y: 0 }} |
| 86 | + className="relative z-10 w-full max-w-2xl text-center" |
| 87 | + > |
| 88 | + <IconSparkles |
| 89 | + size={60} |
| 90 | + className="mx-auto text-brand-orange mb-4" |
| 91 | + /> |
| 92 | + <h1 className="text-3xl sm:text-4xl font-bold mb-2"> |
| 93 | + Just a quick update... |
| 94 | + </h1> |
| 95 | + <p className="text-neutral-300 mb-8"> |
| 96 | + We've added some new features and need a couple more details |
| 97 | + to personalize your experience. |
| 98 | + </p> |
| 99 | + |
| 100 | + <div className="bg-neutral-900/50 border border-neutral-700/50 rounded-2xl p-6 sm:p-8 text-left space-y-6"> |
| 101 | + <p className="whitespace-pre-wrap text-neutral-200"> |
| 102 | + {currentQuestion.question} |
| 103 | + </p> |
| 104 | + |
| 105 | + {currentQuestion.type === "yes-no" && ( |
| 106 | + <div className="flex gap-4 pt-2"> |
| 107 | + <button |
| 108 | + onClick={() => { |
| 109 | + handleAnswer(currentQuestion.id, "yes") |
| 110 | + setTimeout(handleNext, 100) |
| 111 | + }} |
| 112 | + className="px-6 py-2 rounded-lg font-semibold bg-neutral-700 hover:bg-neutral-600" |
| 113 | + > |
| 114 | + Yes |
| 115 | + </button> |
| 116 | + <button |
| 117 | + onClick={() => { |
| 118 | + handleAnswer(currentQuestion.id, "no") |
| 119 | + setTimeout(handleNext, 100) |
| 120 | + }} |
| 121 | + className="px-6 py-2 rounded-lg font-semibold bg-neutral-700 hover:bg-neutral-600" |
| 122 | + > |
| 123 | + No |
| 124 | + </button> |
| 125 | + </div> |
| 126 | + )} |
| 127 | + |
| 128 | + {currentQuestion.type === "text-input" && ( |
| 129 | + <div className="relative pt-2"> |
| 130 | + <div className="absolute left-3 top-1/2 -translate-y-1/2 text-neutral-400"> |
| 131 | + {currentQuestion.icon} |
| 132 | + </div> |
| 133 | + <input |
| 134 | + type="text" |
| 135 | + value={answers[currentQuestion.id] || ""} |
| 136 | + onChange={(e) => |
| 137 | + handleAnswer( |
| 138 | + currentQuestion.id, |
| 139 | + e.target.value |
| 140 | + ) |
| 141 | + } |
| 142 | + placeholder={currentQuestion.placeholder} |
| 143 | + className="w-full pl-10 pr-4 py-3 bg-neutral-800 border border-neutral-700 rounded-lg focus:ring-2 focus:ring-brand-orange" |
| 144 | + autoFocus |
| 145 | + /> |
| 146 | + </div> |
| 147 | + )} |
| 148 | + </div> |
| 149 | + |
| 150 | + <div className="mt-8"> |
| 151 | + <button |
| 152 | + onClick={handleSubmit} |
| 153 | + disabled={ |
| 154 | + isSubmitting || |
| 155 | + currentQuestionIndex !== questions.length - 1 |
| 156 | + } |
| 157 | + className="w-full max-w-xs py-3 px-6 rounded-lg bg-brand-orange text-brand-black font-semibold text-lg transition-all hover:bg-brand-orange/90 disabled:opacity-50 disabled:cursor-not-allowed" |
| 158 | + > |
| 159 | + {isSubmitting ? ( |
| 160 | + <IconLoader className="animate-spin mx-auto" /> |
| 161 | + ) : ( |
| 162 | + "Continue to App" |
| 163 | + )} |
| 164 | + </button> |
| 165 | + </div> |
| 166 | + </motion.div> |
| 167 | + </div> |
| 168 | + ) |
| 169 | +} |
| 170 | + |
| 171 | +export default CompleteProfilePage |
0 commit comments