backend - edit main tab
This commit is contained in:
@@ -4,10 +4,12 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.core.validators import validate_email
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from api.auth.serializers import UserResponseSerializer
|
from api.auth.serializers import UserResponseSerializer
|
||||||
|
|
||||||
from api.models import UserProfile
|
from api.models import UserProfile
|
||||||
|
|
||||||
from api.utils.decorators import handle_exceptions
|
from api.utils.decorators import handle_exceptions
|
||||||
|
|
||||||
class UserDataView(ViewSet):
|
class UserDataView(ViewSet):
|
||||||
@@ -33,3 +35,51 @@ class UserDataView(ViewSet):
|
|||||||
{"error": "User profile not found"},
|
{"error": "User profile not found"},
|
||||||
status=status.HTTP_404_NOT_FOUND
|
status=status.HTTP_404_NOT_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class AccountActions(ViewSet):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
@action(detail=False, methods=['patch'])
|
||||||
|
@handle_exceptions
|
||||||
|
|
||||||
|
def change_data_main_tab(self, request):
|
||||||
|
"""Обновление данных на главной странице аккаунта"""
|
||||||
|
|
||||||
|
user = request.user
|
||||||
|
user_profile = get_object_or_404(UserProfile, user=user)
|
||||||
|
|
||||||
|
# обновляем данные пользователя
|
||||||
|
if 'firstName' in request.data:
|
||||||
|
user.first_name = request.data['firstName']
|
||||||
|
if 'lastName' in request.data:
|
||||||
|
user.last_name = request.data['lastName']
|
||||||
|
if 'email' in request.data:
|
||||||
|
email = request.data['email']
|
||||||
|
validate_email(email) # handle_exceptions обработает ValidationError
|
||||||
|
user.email = email
|
||||||
|
user.username = email
|
||||||
|
|
||||||
|
# обновляем номер телефона
|
||||||
|
if 'phone_number' in request.data:
|
||||||
|
phone = request.data['phone_number']
|
||||||
|
if phone:
|
||||||
|
if len(phone) < 13: # +375XXXXXXXXX
|
||||||
|
raise ValidationError("Номер телефона слишком короткий")
|
||||||
|
|
||||||
|
if len(phone) > 18:
|
||||||
|
raise ValidationError("Номер телефона слишком длинный")
|
||||||
|
|
||||||
|
# проверка на уникальность
|
||||||
|
if UserProfile.objects.filter(phone_number=phone).exclude(user=user).exists():
|
||||||
|
raise ValidationError("Этот номер телефона уже используется")
|
||||||
|
|
||||||
|
user_profile.phone_number = phone
|
||||||
|
|
||||||
|
# сохраняем изменения
|
||||||
|
user.save()
|
||||||
|
user_profile.save()
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
"message": "Данные успешно обновлены",
|
||||||
|
"user": UserResponseSerializer(user).data
|
||||||
|
}, status=status.HTTP_200_OK)
|
||||||
@@ -14,6 +14,8 @@ class UserResponseSerializer(serializers.Serializer):
|
|||||||
phone_number = serializers.CharField(source='userprofile.phone_number')
|
phone_number = serializers.CharField(source='userprofile.phone_number')
|
||||||
image = serializers.CharField(source='userprofile.image')
|
image = serializers.CharField(source='userprofile.image')
|
||||||
uuid = serializers.SerializerMethodField()
|
uuid = serializers.SerializerMethodField()
|
||||||
|
country = serializers.CharField(source='userprofile.country')
|
||||||
|
city = serializers.CharField(source='userprofile.city')
|
||||||
def get_uuid(self, obj):
|
def get_uuid(self, obj):
|
||||||
try:
|
try:
|
||||||
return str(obj.userprofile.uuid)[:6]
|
return str(obj.userprofile.uuid)[:6]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Link from 'next/link'
|
|||||||
import Burger from './ui/Burger'
|
import Burger from './ui/Burger'
|
||||||
import LangSwitcher from './LangSwitcher'
|
import LangSwitcher from './LangSwitcher'
|
||||||
import Button from './ui/Button'
|
import Button from './ui/Button'
|
||||||
|
import UserLogin from './UserLogin'
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
return (
|
return (
|
||||||
@@ -34,18 +35,7 @@ const Header = () => {
|
|||||||
className="hidden md:block bg-orange hover:bg-orange/80 px-4 py-3 text-white"
|
className="hidden md:block bg-orange hover:bg-orange/80 px-4 py-3 text-white"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="hidden md:block text-base font-medium">
|
<UserLogin />
|
||||||
<Link
|
|
||||||
href="/register"
|
|
||||||
className="hover:text-orange transition-colors"
|
|
||||||
>
|
|
||||||
Регистрация
|
|
||||||
</Link>
|
|
||||||
<span> / </span>
|
|
||||||
<Link href="/login" className="hover:text-orange transition-colors">
|
|
||||||
Войти
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-4 md:hidden">
|
<div className="flex items-center space-x-4 md:hidden">
|
||||||
<Link href="/login">
|
<Link href="/login">
|
||||||
|
|||||||
62
frontend/components/UserLogin.tsx
Normal file
62
frontend/components/UserLogin.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import Button from './ui/Button'
|
||||||
|
import useUserStore from '@/app/store/userStore'
|
||||||
|
|
||||||
|
const UserLogin = () => {
|
||||||
|
const { isAuthenticated, user } = useUserStore()
|
||||||
|
const isUserAuth = isAuthenticated && user
|
||||||
|
|
||||||
|
// определяем отображаемое имя и путь для редиректа
|
||||||
|
const getDisplayNameAndPath = () => {
|
||||||
|
if (isUserAuth) {
|
||||||
|
return {
|
||||||
|
name: user?.name || 'пользователь',
|
||||||
|
path: '/account',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'Зарегистрироваться',
|
||||||
|
path: '/register',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, path } = getDisplayNameAndPath()
|
||||||
|
|
||||||
|
if (!isUserAuth) {
|
||||||
|
return (
|
||||||
|
<div className="hidden md:block text-base font-medium">
|
||||||
|
<Link href="/register" className="hover:text-orange transition-colors">
|
||||||
|
Регистрация
|
||||||
|
</Link>
|
||||||
|
<span> / </span>
|
||||||
|
<Link href="/login" className="hover:text-orange transition-colors">
|
||||||
|
Войти
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link href={path} className="ml-2 sm:ml-5">
|
||||||
|
<Button
|
||||||
|
text={isUserAuth ? `Привет, ${name}!` : name}
|
||||||
|
className={`
|
||||||
|
text-sm sm:text-base
|
||||||
|
py-2 sm:py-3
|
||||||
|
px-3 sm:px-4
|
||||||
|
bg-orange text-white
|
||||||
|
flex items-center
|
||||||
|
rounded-2xl
|
||||||
|
whitespace-nowrap
|
||||||
|
hover:bg-orange/80
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserLogin
|
||||||
Reference in New Issue
Block a user