From efccb591ff632a2af9ff7217aa923f5a80ceb68c Mon Sep 17 00:00:00 2001 From: Timofey Date: Fri, 23 May 2025 10:35:25 +0300 Subject: [PATCH] change user membership without payment --- backend/api/account/client/views.py | 6 +- backend/api/urls.py | 4 +- .../(urls)/account/payments/PricingCard.tsx | 20 +++++- frontend/app/(urls)/account/payments/page.tsx | 2 +- frontend/app/api/account/get-plans/route.ts | 26 ------- frontend/app/api/account/membership/route.ts | 69 +++++++++++++++++++ 6 files changed, 95 insertions(+), 32 deletions(-) delete mode 100644 frontend/app/api/account/get-plans/route.ts create mode 100644 frontend/app/api/account/membership/route.ts diff --git a/backend/api/account/client/views.py b/backend/api/account/client/views.py index c44847d..b161b81 100644 --- a/backend/api/account/client/views.py +++ b/backend/api/account/client/views.py @@ -170,13 +170,15 @@ class ChangeUserMembership(ViewSet): @handle_exceptions def change_plan(self, request): """Меняем пользователю тарифный план""" - user_profile = get_object_or_404(User, id=request.user.id) + user = request.user + user_profile = get_object_or_404(UserProfile, user=user) + serializer = PlanChangeSerializer(user_profile, data=request.data) if serializer.is_valid(): serializer.save() return Response({"message": "Тариф успешно изменен"}, status=status.HTTP_200_OK) - + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class GetMembershipData(ViewSet): diff --git a/backend/api/urls.py b/backend/api/urls.py index f5c3fa6..3290e5c 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -13,7 +13,8 @@ UserDataView, AccountActionsView, CityView, CountryView, -GetMembershipData) +GetMembershipData, +ChangeUserMembership) urlpatterns = [ path("v1/faq/", FAQView.as_view(), name='faqMain'), @@ -36,4 +37,5 @@ urlpatterns = [ path("v1/countries/", CountryView.as_view({'get':'get_countries'}), name='get_countries'), path("v1/plans/", GetMembershipData.as_view({'get':'get_pricing_data'}), name='get_pricing_data'), + path("v1/account/change_membership/", ChangeUserMembership.as_view({'patch':'change_plan'}), name='change_plan'), ] \ No newline at end of file diff --git a/frontend/app/(urls)/account/payments/PricingCard.tsx b/frontend/app/(urls)/account/payments/PricingCard.tsx index 3f6dd7e..47bf1f0 100644 --- a/frontend/app/(urls)/account/payments/PricingCard.tsx +++ b/frontend/app/(urls)/account/payments/PricingCard.tsx @@ -18,8 +18,24 @@ const PricingCard: React.FC = ({ const handlePlanChange = async () => { try { setIsLoading(true) - console.log('Changing plan to:', plan) - // const response = await changePlan(plan) -- тут обработка данных запроса на смену плана + + const requestData = { + plan: plan, + } + + const response = await fetch('/api/account/membership', { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestData), + }) + + if (!response.ok) { + const error = await response.json() + console.error('PricingCard - Server error:', error) + throw new Error(error.error || 'Ошибка при создании маршрута') + } // обновляем данные в сторе if (user) { diff --git a/frontend/app/(urls)/account/payments/page.tsx b/frontend/app/(urls)/account/payments/page.tsx index ba4e7cf..c09d1a1 100644 --- a/frontend/app/(urls)/account/payments/page.tsx +++ b/frontend/app/(urls)/account/payments/page.tsx @@ -15,7 +15,7 @@ const AdminPayments = () => { useEffect(() => { const fetchPlans = async () => { try { - const response = await fetch('/api/account/get-plans') + const response = await fetch('/api/account/membership') if (!response.ok) { throw new Error('Failed to fetch plans') } diff --git a/frontend/app/api/account/get-plans/route.ts b/frontend/app/api/account/get-plans/route.ts deleted file mode 100644 index d7d97b8..0000000 --- a/frontend/app/api/account/get-plans/route.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NextRequest } from 'next/server' - -export async function GET(req: NextRequest) { - try { - const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/plans/`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) - - if (!response.ok) { - const error = await response.json() - console.error('API error:', error) - return new Response(JSON.stringify(error), { status: response.status }) - } - - const result = await response.json() - return new Response(JSON.stringify(result), { status: 200 }) - } catch (error) { - console.error('Route handler error:', error) - return new Response(JSON.stringify({ error: 'Internal Server Error' }), { - status: 500, - }) - } -} diff --git a/frontend/app/api/account/membership/route.ts b/frontend/app/api/account/membership/route.ts new file mode 100644 index 0000000..4c39e67 --- /dev/null +++ b/frontend/app/api/account/membership/route.ts @@ -0,0 +1,69 @@ +import { NextRequest } from 'next/server' +import { getServerSession } from 'next-auth' +import { authOptions } from '@/app/api/auth/[...nextauth]/route' + +export async function GET(req: NextRequest) { + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/plans/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + const error = await response.json() + console.error('API error:', error) + return new Response(JSON.stringify(error), { status: response.status }) + } + + const result = await response.json() + return new Response(JSON.stringify(result), { status: 200 }) + } catch (error) { + console.error('Route handler error:', error) + return new Response(JSON.stringify({ error: 'Internal Server Error' }), { + status: 500, + }) + } +} + +export async function PATCH(req: NextRequest) { + try { + const session = await getServerSession(authOptions) + + if (!session) { + return new Response(JSON.stringify({ error: 'Unauthorized' }), { + status: 401, + }) + } + + const data = await req.json() + + const requestBody = { + account_type: data.plan, + } + + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/account/change_membership/`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${session.accessToken}`, + }, + body: JSON.stringify(requestBody), + }) + + if (!response.ok) { + const error = await response.json() + console.error('API Route - Backend error:', error) + return new Response(JSON.stringify(error), { status: response.status }) + } + + const result = await response.json() + return new Response(JSON.stringify(result), { status: 200 }) + } catch (error) { + console.error('API Route - Error:', error) + return new Response(JSON.stringify({ error: 'Internal Server Error' }), { + status: 500, + }) + } +}