Register.jsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { useState } from 'react';
  2. import { useSearchParams, useNavigate, Link } from 'react-router-dom';
  3. import { useLanguage } from '../context/LanguageContext';
  4. import Footer from '../components/Footer';
  5. import { API_HOST } from '../config';
  6. function Register() {
  7. const [searchParams] = useSearchParams();
  8. const navigate = useNavigate();
  9. const { t } = useLanguage();
  10. const [email, setEmail] = useState('');
  11. const [name, setName] = useState('');
  12. const [surname, setSurname] = useState('');
  13. const [isLoading, setIsLoading] = useState(false);
  14. const [error, setError] = useState('');
  15. const selectedPlan = searchParams.get('plan') || 'starter';
  16. const handleSubmit = async (e) => {
  17. e.preventDefault();
  18. setIsLoading(true);
  19. setError('');
  20. try {
  21. // Generate a random ID and token (you might want to handle this differently)
  22. const id = Math.random().toString(36).substr(2, 9);
  23. const token = Math.random().toString(36).substr(2, 9);
  24. const response = await fetch(`${API_HOST}/api/v1/onboard/check-email`, {
  25. method: 'POST',
  26. headers: {
  27. 'Content-Type': 'application/json',
  28. },
  29. body: JSON.stringify({
  30. id,
  31. name,
  32. surname,
  33. email,
  34. token,
  35. plan: selectedPlan,
  36. status: true
  37. }),
  38. });
  39. if (!response.ok) {
  40. throw new Error('Registration failed');
  41. }
  42. // Navigate to registration success page instead of verify-email
  43. navigate('/registration-success');
  44. } catch (err) {
  45. setError(err.message);
  46. } finally {
  47. setIsLoading(false);
  48. }
  49. };
  50. return (
  51. <div className="relative min-h-screen bg-white">
  52. {/* Floating elements */}
  53. <div className="absolute inset-0 overflow-hidden pointer-events-none">
  54. <div className="absolute top-40 left-20 w-32 h-32 bg-brand-purple/10 rounded-full blur-3xl animate-pulse"></div>
  55. <div className="absolute bottom-40 right-20 w-40 h-40 bg-brand-pink/10 rounded-full blur-3xl animate-pulse delay-1000"></div>
  56. </div>
  57. <div className="max-w-[1400px] mx-auto px-4 sm:px-6 lg:px-8 pt-32">
  58. {/* Header section */}
  59. <div className="text-center mb-16">
  60. <h1 className="text-[80px] leading-tight font-light tracking-tight text-gray-900 relative inline-block">
  61. {t('register.title')}
  62. <div className="absolute -top-1 -right-1 w-2 h-2 bg-brand-purple rounded-full"></div>
  63. </h1>
  64. <p className="text-xl text-gray-500 max-w-2xl mx-auto mt-6">
  65. {t('register.selectedPlan')}: <span className="text-brand-purple font-medium">{selectedPlan}</span>
  66. </p>
  67. </div>
  68. {/* Registration Form */}
  69. <div className="max-w-md mx-auto">
  70. <div className="bg-white rounded-2xl shadow-lg p-8">
  71. {error && (
  72. <div className="p-4 rounded-lg bg-red-50 text-red-600 text-sm mb-6">
  73. {error}
  74. </div>
  75. )}
  76. <form onSubmit={handleSubmit} className="space-y-6">
  77. <div>
  78. <label htmlFor="name" className="block text-sm text-gray-700 mb-2">
  79. {t('register.firstName')}
  80. </label>
  81. <input
  82. id="name"
  83. name="name"
  84. type="text"
  85. required
  86. value={name}
  87. onChange={(e) => setName(e.target.value)}
  88. placeholder={t('register.firstNamePlaceholder')}
  89. className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-brand-purple focus:border-transparent"
  90. />
  91. </div>
  92. <div>
  93. <label htmlFor="surname" className="block text-sm text-gray-700 mb-2">
  94. {t('register.lastName')}
  95. </label>
  96. <input
  97. id="surname"
  98. name="surname"
  99. type="text"
  100. required
  101. value={surname}
  102. onChange={(e) => setSurname(e.target.value)}
  103. placeholder={t('register.lastNamePlaceholder')}
  104. className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-brand-purple focus:border-transparent"
  105. />
  106. </div>
  107. <div>
  108. <label htmlFor="email" className="block text-sm text-gray-700 mb-2">
  109. {t('register.email')}
  110. </label>
  111. <input
  112. id="email"
  113. name="email"
  114. type="email"
  115. required
  116. value={email}
  117. onChange={(e) => setEmail(e.target.value)}
  118. placeholder={t('register.emailPlaceholder')}
  119. className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-brand-purple focus:border-transparent"
  120. />
  121. </div>
  122. <button
  123. type="submit"
  124. disabled={isLoading}
  125. className="w-full bg-black text-white rounded-full py-3 text-sm group hover:bg-brand-purple transition-colors duration-300 flex items-center justify-center gap-2 disabled:opacity-50 disabled:hover:bg-black"
  126. >
  127. {isLoading ? (
  128. <span>{t('register.creating')}</span>
  129. ) : (
  130. <span className="flex items-center gap-2">
  131. {t('register.create')}
  132. <span className="transform group-hover:translate-x-1 transition-transform">→</span>
  133. </span>
  134. )}
  135. </button>
  136. </form>
  137. </div>
  138. <div className="mt-6 text-center">
  139. <p className="text-sm text-gray-500">
  140. {t('register.haveAccount')}{' '}
  141. <Link to="/login" className="text-brand-purple hover:text-brand-purple/80 transition-colors">
  142. {t('register.signIn')}
  143. </Link>
  144. </p>
  145. </div>
  146. </div>
  147. </div>
  148. <Footer />
  149. </div>
  150. );
  151. }
  152. export default Register;