register , login model complated. plagiraism component complated(essential part of main page is complated )
This commit is contained in:
@@ -1,38 +1,14 @@
|
||||
/**
|
||||
* Format the number (+998 00 111-22-33)
|
||||
* @param value Number to be formatted
|
||||
* @returns string +998 00 111-22-33
|
||||
*/
|
||||
const formatPhone = (value: string) => {
|
||||
// Keep only numbers
|
||||
const digits = value.replace(/\D/g, '');
|
||||
|
||||
// Return empty string if data is not available
|
||||
if (digits.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const prefix = digits.startsWith('998') ? '+998 ' : '+998 ';
|
||||
|
||||
let formattedNumber = prefix;
|
||||
|
||||
if (digits.length > 3) {
|
||||
formattedNumber += digits.slice(3, 5);
|
||||
}
|
||||
|
||||
if (digits.length > 5) {
|
||||
formattedNumber += ' ' + digits.slice(5, 8);
|
||||
}
|
||||
|
||||
if (digits.length > 8) {
|
||||
formattedNumber += '-' + digits.slice(8, 10);
|
||||
}
|
||||
|
||||
if (digits.length > 10) {
|
||||
formattedNumber += '-' + digits.slice(10, 12);
|
||||
}
|
||||
|
||||
return formattedNumber.trim();
|
||||
if (value.length <= 2) return value;
|
||||
if (value.length <= 5) return `${value.slice(0, 2)} ${value.slice(2)}`;
|
||||
if (value.length <= 7)
|
||||
return `${value.slice(0, 2)} ${value.slice(2, 5)} ${value.slice(5)}`;
|
||||
return `${value.slice(0, 2)} ${value.slice(2, 5)} ${value.slice(
|
||||
5,
|
||||
7,
|
||||
)} ${value.slice(7)}`;
|
||||
};
|
||||
|
||||
export default formatPhone;
|
||||
const normalizeDigits = (value: string) => value.replace(/\D/g, '').slice(0, 9);
|
||||
|
||||
export { formatPhone, normalizeDigits };
|
||||
|
||||
18
src/shared/ui/motion.tsx
Normal file
18
src/shared/ui/motion.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
function MotionWrapper({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95, y: 10 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.95, y: 10 }}
|
||||
transition={{ duration: 0.2, ease: 'easeOut' }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
export { MotionWrapper };
|
||||
19
src/shared/ui/phonePrefix.tsx
Normal file
19
src/shared/ui/phonePrefix.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Phone } from 'lucide-react';
|
||||
|
||||
function PhonePrefix({ isFocused }: { isFocused: boolean }) {
|
||||
return (
|
||||
<div className="absolute left-4 top-1/2 -translate-y-1/2 flex items-center gap-2 pointer-events-none">
|
||||
<Phone
|
||||
className={`h-4 w-4 ${isFocused ? 'text-primary' : 'text-muted-foreground'}`}
|
||||
/>
|
||||
<span
|
||||
className={`font-semibold text-base ${isFocused ? 'text-primary' : 'text-muted-foreground'}`}
|
||||
>
|
||||
+998
|
||||
</span>
|
||||
<span className="text-muted-foreground/40">|</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PhonePrefix;
|
||||
26
src/shared/zustand/auth.ts
Normal file
26
src/shared/zustand/auth.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface LoginModalStore {
|
||||
openLoginModal: boolean;
|
||||
toggleLoginModal: () => void;
|
||||
}
|
||||
|
||||
const useLoginModal = create<LoginModalStore>((set) => ({
|
||||
openLoginModal: false,
|
||||
toggleLoginModal: () =>
|
||||
set((state) => ({ openLoginModal: !state.openLoginModal })),
|
||||
}));
|
||||
|
||||
// REGISTER MODAL STORE ====================== ////////
|
||||
interface RegisterModalStore {
|
||||
openRegisterModal: boolean;
|
||||
toggleRegisterModal: () => void;
|
||||
}
|
||||
|
||||
const useRegisterModal = create<RegisterModalStore>((set) => ({
|
||||
openRegisterModal: false,
|
||||
toggleRegisterModal: () =>
|
||||
set((state) => ({ openRegisterModal: !state.openRegisterModal })),
|
||||
}));
|
||||
|
||||
export { useLoginModal, useRegisterModal };
|
||||
Reference in New Issue
Block a user