<!-- home.html -->

{% extends "base.html" %}
{% load static %}

{% block content %}

    {% if user.is_authenticated %}
    
        <div class="text-center mt-40 p-8 text-[#2c3e50] bg-[#f0f4f8] rounded-xl max-w-3xl mx-auto my-10">
            <h1 class="text-[2.2rem] font-bold mb-2 text-[#3498db]">
                به صفحه خانه خوش آمدید!
            </h1>
            <p class="mt-4 text-xl">
                کاربر: {{ user.fullname }}
            </p>
            <p class="mt-7 text-5xl">
                🎉
            </p>
            <a href="{% url 'logout' %}" class="mt-10 inline-block text-2xl text-red-600 hover:text-red-800 transition border py-2 px-7 rounded-xl">
                خروج
            </a>
        </div>

    {% else %}

        <article class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100 dark:from-gray-800 dark:to-gray-900">
            <div class="backdrop-blur-xl bg-white/20 dark:bg-gray-700/30 shadow-2xl dark:shadow-white/40 border border-white/20 dark:border-gray-600/30 w-full max-w-sm p-8 rounded-3xl text-right space-y-6">
                <div id="phone-entry-section">
                    <!-- Header -->
                    <div class="flex flex-col items-center space-y-2">
                    <div class="bg-blue-600 text-white w-14 h-14 flex items-center justify-center rounded-full shadow-lg">
                        <i class="fas fa-user-tie text-2xl"></i>
                    </div>
                    <h2 class="text-xl font-bold text-blue-800 dark:text-white/90">ورود به سیستم</h2>
                    <p class="text-sm text-gray-700 dark:text-gray-300">شماره موبایل خود را وارد کنید</p>
                    </div>

                    <!-- Phone Input Form -->
                    <form id="phone-form">
                    <label for="phone" class="block text-sm font-medium text-gray-800 dark:text-gray-200 mb-1">شماره موبایل</label>
                    <div class="relative" dir="ltr">
                        <div class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-700 dark:text-gray-300 font-semibold select-none z-10">+98</div>
                        
                        <!-- Actual input (hidden text) -->
                        <input type="tel" id="phone" name="phone"
                            class="w-full rounded-xl border border-gray-300 dark:border-gray-600 bg-transparent hover:border-blue-500 font-bold px-14 py-4 text-transparent caret-blue-600 text-left tracking-widest focus:ring-2 focus:ring-blue-500 focus:outline-none shadow-sm appearance-none">
                        
                        <!-- Dash placeholder -->
                        <div class="absolute left-0 top-0 pointer-events-none text-gray-400 pl-14 pr-12 h-full flex items-center font-bold tracking-widest" id="dash-placeholder">
                        <span id="part1" class="transition-all duration-200 ease-in-out inline-block"><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span></span>&nbsp;
                        <span id="part2" class="transition-all duration-200 ease-in-out inline-block"><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span></span>&nbsp;
                        <span id="part3" class="transition-all duration-200 ease-in-out inline-block"><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span><span class="transition-all duration-200 ease-in-out inline-block">-</span></span>
                        </div>
                        
                        <!-- Phone icon -->
                        <div class="input-icon absolute right-3 top-1/2 -translate-y-1/2">
                        <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 transition-all duration-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
                        </svg>
                        </div>
                    </div>

                    <button type="submit"
                            class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded-xl transition duration-200 shadow-lg mt-6">
                        دریافت کد تأیید
                    </button>
                    </form>
                </div>

                <div id="verification-section" class="hidden">
                    <!-- Header -->
                    <div class="flex flex-col items-center space-y-2">
                    <div class="bg-blue-500 text-white w-14 h-14 flex items-center justify-center rounded-full shadow-lg">
                        <svg class="w-7 h-7" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
                        </svg>
                    </div>
                    <h2 class="text-xl font-bold text-blue-800 dark:text-white/90">تأیید شماره موبایل</h2>
                    <p class="text-sm text-gray-700 dark:text-gray-300">کد ارسال شده را وارد کنید</p>
                    </div>

                    <!-- Verification Info -->
                    <div class="dark:text-white/85 dark:bg-transparent p-3 rounded-xl mb-3 text-center">
                    <p>کد تأیید به شماره <span id="entered-phone" class="font-bold" dir="ltr">09123456789</span> ارسال شد</p>
                    <p class="text-xs mt-1 text-gray-600 dark:text-gray-400">در صورت عدم دریافت کد، پس از <span id="countdown" class="text-gray-500 dark:text-gray-400">02:00</span> شماره موبایل مجدداً درخواست می‌شود</p>
                    </div>

                    <!-- Verification Code Form -->
                    <form id="verification-form">
                    <div class="flex justify-center gap-2.5 direction-ltr mb-5">
                        <input type="text" dir="ltr" class="w-14 h-16 text-center text-2xl font-bold border-2 border-gray-300 dark:border-gray-500 rounded-xl bg-white/30 dark:bg-gray-600/30 transition-all duration-200 focus:border-blue-500 focus:outline-none focus:scale-105 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-900" maxlength="1" inputmode="numeric" pattern="[0-9]*" data-index="0">
                        <input type="text" dir="ltr" class="w-14 h-16 text-center text-2xl font-bold border-2 border-gray-300 dark:border-gray-500 rounded-xl bg-white/30 dark:bg-gray-600/30 transition-all duration-200 focus:border-blue-500 focus:outline-none focus:scale-105 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-900" maxlength="1" inputmode="numeric" pattern="[0-9]*" data-index="1">
                        <input type="text" dir="ltr" class="w-14 h-16 text-center text-2xl font-bold border-2 border-gray-300 dark:border-gray-500 rounded-xl bg-white/30 dark:bg-gray-600/30 transition-all duration-200 focus:border-blue-500 focus:outline-none focus:scale-105 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-900" maxlength="1" inputmode="numeric" pattern="[0-9]*" data-index="2">
                        <input type="text" dir="ltr" class="w-14 h-16 text-center text-2xl font-bold border-2 border-gray-300 dark:border-gray-500 rounded-xl bg-white/30 dark:bg-gray-600/30 transition-all duration-200 focus:border-blue-500 focus:outline-none focus:scale-105 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-900" maxlength="1" inputmode="numeric" pattern="[0-9]*" data-index="3">
                    </div>
                    
                    <input type="hidden" id="verification-code" name="verification-code">
                    <input type="hidden" id="full-phone" name="full-phone">

                    <button type="submit"
                            class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 rounded-xl transition duration-200 shadow-lg">
                        تأیید و ورود
                    </button>
                    </form>

                    <p class="text-xs text-center text-gray-600 dark:text-gray-400 mt-4">
                    شماره را اشتباه وارد کرده‌اید؟ 
                    <a href="#" id="change-number" class="text-blue-600 dark:text-blue-400 hover:underline">تغییر شماره موبایل</a>
                    </p>
                </div>

                <p class="text-xs text-center text-gray-600 dark:text-gray-400">
                    با ورود، <a href="#" class="text-blue-600 dark:text-blue-400 hover:underline">قوانین استفاده</a> را می‌پذیرید.
                </p>
            </div>

            <script>
            const phoneInput = document.getElementById('phone');
            const dashPlaceholder = document.getElementById('dash-placeholder');
            const part1 = document.getElementById('part1');
            const part2 = document.getElementById('part2');
            const part3 = document.getElementById('part3');
            const phoneIcon = document.querySelector('.input-icon svg');
            const phoneForm = document.getElementById('phone-form');
            const verificationSection = document.getElementById('verification-section');
            const phoneEntrySection = document.getElementById('phone-entry-section');
            const enteredPhoneSpan = document.getElementById('entered-phone');
            const fullPhoneInput = document.getElementById('full-phone');
            const verificationForm = document.getElementById('verification-form');
            const verificationCodeInput = document.getElementById('verification-code');
            const codeInputs = document.querySelectorAll('#verification-form input[type="text"]');
            const countdownEl = document.getElementById('countdown');
            const changeNumberBtn = document.getElementById('change-number');
            
            let verificationCode = '';
            let countdownInterval;
            let timeLeft = 120; // 2 minutes in seconds
            let attempts = 0;
            const MAX_ATTEMPTS = 2; // Allow 2 attempts before returning to phone entry

            // Function to convert Persian/Arabic digits to English
            function toEnglishDigits(str) {
                const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
                const arabicDigits = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
                
                return str.split('').map(char => {
                const persianIndex = persianDigits.indexOf(char);
                if (persianIndex !== -1) return persianIndex;
                
                const arabicIndex = arabicDigits.indexOf(char);
                if (arabicIndex !== -1) return arabicIndex;
                
                return char;
                }).join('');
            }

            // Phone number input handling
            phoneInput.addEventListener('input', function () {
                let raw = toEnglishDigits(phoneInput.value);
                raw = raw.replace(/\D/g, '');
                
                // Strict validation: Only allow numbers starting with 9
                if (raw.length > 0 && !raw.startsWith('9')) {
                phoneInput.value = '';
                raw = '';
                return;
                }
                
                // Update dash placeholders with animation
                updateDashPlaceholder(raw);
                
                // Limit to 10 digits
                if (raw.length > 10) {
                raw = raw.substring(0, 10);
                phoneInput.value = raw;
                } else {
                phoneInput.value = raw;
                }
                
                // Validate phone number and update icon
                validatePhoneNumber(raw);
            });

            function updateDashPlaceholder(raw) {
                // First part (3 digits)
                updatePart(part1, raw.substring(0, 3), 3);
                
                // Second part (3 digits)
                updatePart(part2, raw.substring(3, 6), 3);
                
                // Third part (4 digits)
                updatePart(part3, raw.substring(6, 10), 4);
            }
            
            function updatePart(partElement, digits, maxLength) {
                const digitElements = partElement.querySelectorAll('span');
                
                for (let i = 0; i < maxLength; i++) {
                if (i < digits.length) {
                    // Animate digit entry
                    if (digitElements[i].textContent === '-' && digits[i] !== '-') {
                    digitElements[i].classList.add('transform', 'scale-125', 'text-green-500');
                    setTimeout(() => {
                        digitElements[i].classList.remove('transform', 'scale-125', 'text-green-500');
                    }, 200);
                    }
                    digitElements[i].textContent = digits[i] || '-';
                } else {
                    digitElements[i].textContent = '-';
                }
                }
            }
            
            function validatePhoneNumber(raw) {
                // Iranian phone number validation (starts with 9 and 10 digits)
                const isValid = raw.length === 10 && raw.startsWith('9');
                
                // Update icon color
                phoneIcon.classList.remove('text-green-500', 'text-red-500', 'text-gray-400');
                
                if (raw.length === 0) {
                phoneIcon.classList.add('text-gray-400');
                } else if (isValid) {
                phoneIcon.classList.add('text-green-500');
                } else {
                phoneIcon.classList.add('text-red-500');
                }
            }

            // Handle phone form submission
            phoneForm.addEventListener('submit', function(e) {
                e.preventDefault();
                
                const rawPhone = phoneInput.value.replace(/\D/g, '');
                
                // Validate phone number
                if (rawPhone.length === 10 && rawPhone.startsWith('9')) {
                // Generate random 4-digit verification code
                verificationCode = Math.floor(1000 + Math.random() * 9000).toString();
                console.log('Verification Code:', verificationCode); // For testing purposes
                
                // Show verification section with animation
                phoneEntrySection.classList.add('hidden');
                verificationSection.classList.remove('hidden');
                verificationSection.classList.add('animate-fade-in');
                
                // Display the entered phone number
                const formattedPhone = '0' + rawPhone.substring(0, 3) + ' ' + rawPhone.substring(3, 6) + ' ' + rawPhone.substring(6);
                enteredPhoneSpan.textContent = formattedPhone;
                fullPhoneInput.value = '+98' + rawPhone;
                
                // Start countdown timer
                startCountdown();
                
                // Focus first code input
                setTimeout(() => {
                    codeInputs[0].focus();
                }, 100);
                }
            });

            // Verification code input handling
            codeInputs.forEach(input => {
                input.addEventListener('input', function() {
                const index = parseInt(this.dataset.index);
                
                // Move to next input if a digit is entered
                if (this.value.length === 1) {
                    if (index < 3) {
                    codeInputs[index + 1].focus();
                    } else {
                    this.blur();
                    }
                }
                
                // Update hidden input with full code
                updateVerificationCode();
                });
                
                // Handle backspace
                input.addEventListener('keydown', function(e) {
                const index = parseInt(this.dataset.index);
                
                if (e.key === 'Backspace' && this.value.length === 0 && index > 0) {
                    codeInputs[index - 1].focus();
                }
                });
            });

            function updateVerificationCode() {
                let code = '';
                codeInputs.forEach(input => {
                code += input.value;
                });
                verificationCodeInput.value = code;
            }

            // Verification form submission
            verificationForm.addEventListener('submit', function(e) {
                e.preventDefault();
                
                const enteredCode = verificationCodeInput.value;
                
                if (enteredCode.length === 4) {
                if (enteredCode === verificationCode) {
                    // Code is correct - simulate successful login
                    alert('ورود با موفقیت انجام شد!');
                    // Here you would typically redirect or proceed with login
                } else {
                    // Code is incorrect
                    attempts++;
                    
                    // Add red border and shake animation to all code inputs
                    codeInputs.forEach(input => {
                    input.classList.add('border-red-500', 'animate-shake');
                    });
                    
                    // Clear inputs after animation
                    setTimeout(() => {
                    codeInputs.forEach(input => {
                        input.value = '';
                        input.classList.remove('border-red-500', 'animate-shake');
                    });
                    // Focus the first input box
                    codeInputs[0].focus();
                    updateVerificationCode();
                    }, 500);
                    
                    if (attempts >= MAX_ATTEMPTS) {
                    // After 2 failed attempts, return to phone entry
                    setTimeout(() => {
                        returnToPhoneEntry();
                    }, 1000);
                    }
                }
                }
            });

            function animatePhoneClear() {
                const raw = phoneInput.value.replace(/\D/g, '');
                if (raw.length === 0) return;
                
                // Animate each digit removal
                const digitElements = document.querySelectorAll('.dash-placeholder span span');
                let delay = 0;
                
                // Animate from right to left
                for (let i = digitElements.length - 1; i >= 0; i--) {
                if (digitElements[i].textContent !== '-') {
                    setTimeout(() => {
                    digitElements[i].classList.add('transform', 'scale-90', 'opacity-0');
                    setTimeout(() => {
                        digitElements[i].textContent = '-';
                        digitElements[i].classList.remove('transform', 'scale-90', 'opacity-0');
                    }, 200);
                    }, delay);
                    delay += 50;
                }
                }
                
                return delay + 200; // Return total animation time
            }

            function returnToPhoneEntry() {
                // Animate phone number clearing
                const animationTime = animatePhoneClear();
                
                // Clear phone input after animation
                setTimeout(() => {
                phoneInput.value = '';
                updateDashPlaceholder('');
                validatePhoneNumber('');
                
                // Hide verification section with animation
                verificationSection.classList.add('animate-fade-out');
                setTimeout(() => {
                    verificationSection.classList.add('hidden');
                    verificationSection.classList.remove('animate-fade-out', 'animate-fade-in');
                    
                    // Show phone entry with animation
                    phoneEntrySection.classList.remove('hidden');
                    phoneEntrySection.classList.add('animate-slide-down');
                    setTimeout(() => {
                    phoneEntrySection.classList.remove('animate-slide-down');
                    }, 300);
                }, 300);
                
                // Reset attempts counter
                attempts = 0;
                
                // Clear verification inputs
                codeInputs.forEach(input => input.value = '');
                updateVerificationCode();
                
                // Focus phone input
                phoneInput.focus();
                }, animationTime);
            }

            // Countdown timer functions
            function startCountdown() {
                timeLeft = 120; // Reset to 2 minutes
                updateCountdownDisplay();
                
                clearInterval(countdownInterval);
                countdownInterval = setInterval(() => {
                timeLeft--;
                updateCountdownDisplay();
                
                if (timeLeft <= 0) {
                    clearInterval(countdownInterval);
                    // Automatically return to phone entry when time is up
                    setTimeout(() => {
                    returnToPhoneEntry();
                    }, 500);
                }
                }, 1000);
            }

            function updateCountdownDisplay() {
                const minutes = Math.floor(timeLeft / 60);
                const seconds = timeLeft % 60;
                countdownEl.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
            }

            // Change number functionality
            changeNumberBtn.addEventListener('click', function(e) {
                e.preventDefault();
                returnToPhoneEntry();
            });
            </script>
        </article>

    {% endif %}

{% endblock content %}

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager,
    AbstractBaseUser,
)
from django.core.validators import RegexValidator, MinLengthValidator
from django.utils.translation import gettext_lazy as _


class MyUserManager(BaseUserManager):
    def create_user(self, username, email=None, password=None, **extra_fields):
        if not username:
            raise ValueError("کاربران باید نام کاربری داشته باشند")

        email = self.normalize_email(email) if email else None

        user = self.model(
            username=username,
            email=email,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_admin', True)
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if not extra_fields.get('is_admin'):
            raise ValueError('کاربر سطح بالا باید is_admin=True باشد.')

        return self.create_user(
            username=username,
            email=email,
            password=password,
            **extra_fields
        )


class MyUser(AbstractBaseUser):
    # اطلاعات شخصی
    profile = models.ImageField(
        upload_to='dynamic/profile/%Y/%m/%d/',
        blank=True,
        null=True,
        verbose_name="تصویر کاربر"
    )
    fullname = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name="نام کامل"
    )
    username = models.CharField(
        max_length=100,
        unique=True,
        verbose_name="نام کاربری",
        validators=[
            RegexValidator(
                r'^[\w.@+-]+\Z',
                "نام کاربری فقط می‌تواند شامل حروف، اعداد و @/./+/-/_ باشد."
            )
        ]
    )
    national = models.CharField(
        max_length=10,
        verbose_name="کد ملی",
        blank=True,
        null=True,
        validators=[
            MinLengthValidator(10),
            RegexValidator(r'^\d+$', "کد ملی باید فقط شامل اعداد باشد.")
        ]
    )
    email = models.EmailField(
        max_length=255,
        unique=True,
        blank=True,
        null=True,
        verbose_name="ایمیل"
    )
    mobile = models.CharField(
        max_length=15,
        unique=True,
        verbose_name="تلفن همراه",
        validators=[
            RegexValidator(
                r'^\+?1?\d{9,15}$',
                "شماره موبایل باید در قالب بین‌المللی وارد شود."
            )
        ]
    )
    
    # نقش و موقعیت
    ROLE_CHOICES = [
        ('Manager', 'مدیر ارشد'),
        ('Accounter', 'حسابدار'),
        ('Warehouser', 'انباردار')
    ]
    role = models.CharField(
        max_length=20,
        choices=ROLE_CHOICES,
        blank=True,
        null=True,
        verbose_name="نقش کاربر"
    )
    birthday = models.DateField(
        blank=True,
        null=True,
        verbose_name="تاریخ تولد"
    )
    province = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name="استان"
    )
    city = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name="شهر"
    )
    address = models.TextField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="آدرس"
    )
    post = models.CharField(
        max_length=10,
        blank=True,
        null=True,
        verbose_name="کد پستی",
        validators=[
            MinLengthValidator(10),
            RegexValidator(r'^\d+$', "کد پستی باید فقط شامل اعداد باشد.")
        ]
    )
    
    # وضعیت و زمان‌ها
    approved = models.BooleanField(
        default=False,
        verbose_name="امضای الکترونیک"
    )
    createded = models.DateTimeField(
        auto_now_add=True,
        verbose_name="زمان ایجاد"
    )
    
    # سطوح دسترسی
    is_active = models.BooleanField(
        default=True,
        verbose_name="کاربر"
    )
    is_admin = models.BooleanField(
        default=False,
        verbose_name="ادمین"
    )
    is_staff = models.BooleanField(
        default=False,
        verbose_name="مدیریت"
    )
    is_superuser = models.BooleanField(
        default=False,
        verbose_name="سوپریوزر"
    )

    objects = MyUserManager()

    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.username

    def has_perm(self, perm, obj=None):
        """بررسی وجود مجوز خاص برای کاربر"""
        return self.is_admin or self.is_superuser

    def has_module_perms(self, app_label):
        """بررسی دسترسی کاربر به ماژول‌های خاص"""
        return self.is_admin or self.is_superuser
    
    from django.views.generic import TemplateView

class HomeView(TemplateView):
    template_name = 'home.html' from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import HomeView

urlpatterns = [
    path('', HomeView.as_view(), name='home'),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 این کد من برای لاگین کاربر هست که کاربر با استفاده از شماره تلفن که در فرم وارد میکنه باید یه کد براش ارسال بشه که فعلا اینکد تو ترمینال پرینت میشه و وقتی کاربر کد رو تو باکس های کد وارد کرد اگه درست بود وارد بشه وقسمت خانه نمایش داده بشه اگه نه هم ککه طبق کن همه قسمت ها به غیر از مدل رو برا م بفرست کامل در ضمن لاگین و قسمت خانه همه در صفحه هوم هستن  نیاز به مسیر جدید نیست