modal location updated

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-04-01 12:12:35 +05:00
parent 6041e6a719
commit 011845571f
9 changed files with 71 additions and 41 deletions

View File

@@ -9,8 +9,7 @@ import {
import PhonePrefix from '../../../../shared/ui/phonePrefix'; import PhonePrefix from '../../../../shared/ui/phonePrefix';
import { MotionWrapper } from '../../../../shared/ui/motion'; import { MotionWrapper } from '../../../../shared/ui/motion';
import { useLoginForm } from '../lib/useLoginForm'; import { useLoginForm } from '../lib/useLoginForm';
import { useLoginModal } from '@/shared/zustand/auth'; import { useLoginModal, useRegisterModal } from '@/shared/zustand/auth';
import Link from 'next/link';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
export function LoginForm() { export function LoginForm() {
@@ -20,6 +19,9 @@ export function LoginForm() {
const { phone, setPhone, submit, error, loading } = useLoginForm(); const { phone, setPhone, submit, error, loading } = useLoginForm();
const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal); const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal);
const toggleRegisterModal = useRegisterModal(
(state) => state.toggleRegisterModal,
);
const handlePhoneChange = useCallback( const handlePhoneChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => { (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -149,14 +151,17 @@ export function LoginForm() {
</div> </div>
{/* Register hint */} {/* Register hint */}
<p className="text-center text-[0.78rem] text-stone-400"> <p className="text-center text-[0.78rem] text-stone-400 flex items-center justify-center gap-2">
{t('registerPrompt')} {t('registerPrompt')}
<Link <p
href="/register" onClick={() => {
className="text-stone-800 underline underline-offset-2 hover:text-stone-600 transition-colors" toggleLoginModal();
toggleRegisterModal();
}}
className="text-stone-800 hover:cursor-pointer underline underline-offset-2 hover:text-stone-600 transition-colors"
> >
{t('registerLink')} {t('registerLink')}
</Link> </p>
</p> </p>
</form> </form>
</div> </div>

View File

@@ -5,6 +5,7 @@ import { useRegisterForm } from '../lib/useRegisterForm';
import { formatPhone, normalizeDigits } from '@/shared/lib/formatPhone'; import { formatPhone, normalizeDigits } from '@/shared/lib/formatPhone';
import PhonePrefix from '@/shared/ui/phonePrefix'; import PhonePrefix from '@/shared/ui/phonePrefix';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useLoginModal, useRegisterModal } from '@/shared/zustand/auth';
function Field({ function Field({
id, id,
@@ -66,6 +67,7 @@ function Field({
export function RegisterFormUI() { export function RegisterFormUI() {
const [phone, setPhone] = React.useState(''); const [phone, setPhone] = React.useState('');
const t = useTranslations('Auth.Register'); const t = useTranslations('Auth.Register');
const t_login = useTranslations('Auth.Login');
const tCommon = useTranslations('Common'); const tCommon = useTranslations('Common');
const { const {
registerData, registerData,
@@ -77,6 +79,10 @@ export function RegisterFormUI() {
handleSubmit, handleSubmit,
setItem, setItem,
} = useRegisterForm(); } = useRegisterForm();
const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal);
const toggleRegisterModal = useRegisterModal(
(state) => state.toggleRegisterModal,
);
const [isFocused, setIsFocused] = React.useState(false); const [isFocused, setIsFocused] = React.useState(false);
const handlePhoneChange = useCallback( const handlePhoneChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => { (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -233,6 +239,29 @@ export function RegisterFormUI() {
)} )}
</button> </button>
</form> </form>
{/* Divider */}
<div className="relative flex items-center gap-3 py-1">
<span className="h-px flex-1 bg-stone-200" />
<span className="text-[0.65rem] font-medium uppercase tracking-widest text-stone-400">
{tCommon('or')}
</span>
<span className="h-px flex-1 bg-stone-200" />
</div>
{/* Register hint */}
<p className="text-center text-[0.78rem] text-stone-400 flex items-center justify-center gap-2">
{t('loginPrompt')}
<p
onClick={() => {
toggleLoginModal();
toggleRegisterModal();
}}
className="text-stone-800 hover:cursor-pointer underline underline-offset-2 hover:text-stone-600 transition-colors"
>
{t_login('title')}
</p>
</p>
</div> </div>
); );
} }

View File

@@ -188,7 +188,8 @@
"namePlaceholder": "Ali", "namePlaceholder": "Ali",
"surnamePlaceholder": "Karimov", "surnamePlaceholder": "Karimov",
"terms": "I agree to the Terms of Service and Privacy Policy", "terms": "I agree to the Terms of Service and Privacy Policy",
"submitButton": "Create account" "submitButton": "Create account",
"loginPrompt": "Already have an account?"
} }
}, },
"Payment": { "Payment": {

View File

@@ -188,7 +188,8 @@
"namePlaceholder": "Али", "namePlaceholder": "Али",
"surnamePlaceholder": "Каримов", "surnamePlaceholder": "Каримов",
"terms": "Я согласен с Условиями обслуживания и Политикой конфиденциальности", "terms": "Я согласен с Условиями обслуживания и Политикой конфиденциальности",
"submitButton": "Создать аккаунт" "submitButton": "Создать аккаунт",
"loginPrompt": "Уже есть аккаунт?"
} }
}, },
"Payment": { "Payment": {

View File

@@ -192,6 +192,7 @@ declare const messages: {
surnamePlaceholder: 'Karimov'; surnamePlaceholder: 'Karimov';
terms: "Men Xizmat ko'rsatish shartlari va Maxfiylik siyosatiga roziman"; terms: "Men Xizmat ko'rsatish shartlari va Maxfiylik siyosatiga roziman";
submitButton: 'Hisob yaratish'; submitButton: 'Hisob yaratish';
loginPrompt: 'Hisobingiz bormi?';
}; };
}; };
Payment: { Payment: {

View File

@@ -188,7 +188,8 @@
"namePlaceholder": "Ali", "namePlaceholder": "Ali",
"surnamePlaceholder": "Karimov", "surnamePlaceholder": "Karimov",
"terms": "Men Xizmat ko'rsatish shartlari va Maxfiylik siyosatiga roziman", "terms": "Men Xizmat ko'rsatish shartlari va Maxfiylik siyosatiga roziman",
"submitButton": "Hisob yaratish" "submitButton": "Hisob yaratish",
"loginPrompt": "Hisobingiz bormi?"
} }
}, },
"Payment": { "Payment": {

View File

@@ -1,5 +1,10 @@
import type { FC } from 'react'; 'use client';
import { motion, type MotionStyle, type MotionValue } from 'framer-motion'; import {
motion,
useScroll,
useTransform,
type MotionStyle,
} from 'framer-motion';
import { fadeUp, stagger } from '../animations'; import { fadeUp, stagger } from '../animations';
import { C } from '../tokens'; import { C } from '../tokens';
import { STATS } from '../constants'; import { STATS } from '../constants';
@@ -10,16 +15,15 @@ import Section from './Section';
import Stat from './Stat'; import Stat from './Stat';
import StartButton from './StartButton'; import StartButton from './StartButton';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useLoginModal } from '@/shared/zustand/auth';
interface HeroProps { const Hero = () => {
onStart: () => void;
blobY: MotionValue<number>;
}
const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const t = useTranslations('Hero'); const t = useTranslations('Hero');
const tStats = useTranslations('Stats'); const tStats = useTranslations('Stats');
const { scrollY } = useScroll();
const blobY = useTransform(scrollY, [0, 600], [0, 80]);
const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal);
const getTranslatedLabel = (label: string) => { const getTranslatedLabel = (label: string) => {
switch (label) { switch (label) {
@@ -149,7 +153,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
flexWrap: 'wrap', flexWrap: 'wrap',
}} }}
> >
<StartButton onClick={onStart} /> <StartButton onClick={() => toggleLoginModal()} />
<span <span
style={{ style={{
color: C.textMuted, color: C.textMuted,

View File

@@ -1,4 +1,5 @@
import type { FC } from 'react'; 'use client';
import { useRef } from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { fadeUp } from '../animations'; import { fadeUp } from '../animations';
import { C } from '../tokens'; import { C } from '../tokens';
@@ -8,15 +9,13 @@ import Section from './Section';
import StartButton from './StartButton'; import StartButton from './StartButton';
import StepCard from './StepCard'; import StepCard from './StepCard';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useLoginModal } from '@/shared/zustand/auth';
interface StepsSectionProps { const StepsSection = () => {
stepsRef: React.RefObject<HTMLDivElement | null>;
onScrollTop: () => void;
}
const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const t = useTranslations('StepsSection'); const t = useTranslations('StepsSection');
const stepsRef = useRef<HTMLDivElement>(null);
const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal);
return ( return (
<div <div
@@ -120,7 +119,7 @@ const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
{t('ctaDescription')} {t('ctaDescription')}
</p> </p>
</div> </div>
<StartButton onClick={onScrollTop} /> <StartButton onClick={() => toggleLoginModal()} />
</motion.div> </motion.div>
</div> </div>
</Section> </Section>

View File

@@ -1,27 +1,16 @@
'use client'; 'use client';
import { useRef, type FC } from 'react';
import { useScroll, useTransform } from 'framer-motion';
import Hero from './components/Hero'; import Hero from './components/Hero';
import InfoSection from './components/InfoSection'; import InfoSection from './components/InfoSection';
import StepsSection from './components/StepsSection'; import StepsSection from './components/StepsSection';
import Ticker from './components/Ticker'; import Ticker from './components/Ticker';
const PlagiarismLanding: FC = () => { const PlagiarismLanding = () => {
const stepsRef = useRef<HTMLDivElement>(null);
const { scrollY } = useScroll();
const blobY = useTransform(scrollY, [0, 600], [0, 80]);
const scrollToSteps = () =>
stepsRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
const scrollToTop = () => window.scrollTo({ top: 0, behavior: 'smooth' });
return ( return (
<> <>
<Hero onStart={scrollToSteps} blobY={blobY} /> <Hero />
<Ticker /> <Ticker />
<InfoSection /> <InfoSection />
<StepsSection stepsRef={stepsRef} onScrollTop={scrollToTop} /> <StepsSection />
</> </>
); );
}; };