Added create review endpoint

This commit is contained in:
Umar Adilov 2025-05-07 22:03:37 +05:00
parent 2872d6c1dd
commit 54dc9c243b
8 changed files with 90 additions and 14 deletions

View File

@ -2,7 +2,7 @@ import { jsonToGraphQLQuery } from 'json-to-graphql-query';
export const requestTaylor = async (query: object, variables?: object) => { export const requestTaylor = async (query: object, variables?: object) => {
const body = JSON.stringify({ const body = JSON.stringify({
query: jsonToGraphQLQuery({ query }), query: jsonToGraphQLQuery(query),
variables, variables,
}); });

View File

@ -1,4 +1,4 @@
import { EnumType } from 'json-to-graphql-query'; import { EnumType, VariableType } from 'json-to-graphql-query';
export const stationsRequest = { export const stationsRequest = {
_azs: { _azs: {
@ -146,6 +146,18 @@ export const historyRequest = {
export const reviewsRequest = { export const reviewsRequest = {
_otzyvy: { _otzyvy: {
__args: {
filtersSet: {
conjunction: new EnumType('and'),
filtersSet: [
{
field: new EnumType('_status'),
operator: 'contains',
value: 'Опубликовано',
},
],
},
},
records: { records: {
id: true, id: true,
_name: true, _name: true,
@ -182,3 +194,17 @@ export const certificatesRequest = {
}, },
}, },
}; };
export const createReviewMutation = {
__variables: {
review: 'TableOtzyvyMutationParameters',
},
_otzyvy: {
createRecord: {
__args: {
records: [new VariableType('review')],
},
id: true,
},
},
};

View File

@ -0,0 +1,32 @@
import { NextRequest } from 'next/server';
import { z } from 'zod';
import { requestTaylor } from '@/app/api-utlities/clients/taylor.client';
import { createReviewMutation } from '@/app/api-utlities/requests/common';
export const POST = async (req: NextRequest) => {
const body = await req.json();
const validatedRequest = z
.object({
name: z.string(),
text: z.string(),
rating: z.number().min(0).max(5),
})
.parse(body);
await requestTaylor(
{ mutation: createReviewMutation },
{
review: {
_name: validatedRequest.name,
_otzyv: validatedRequest.text,
_rejting: validatedRequest.rating,
},
},
);
return new Response(JSON.stringify({ success: true }), {
status: 201,
});
};

View File

@ -10,7 +10,8 @@ export interface TransactionResponse {
export interface Transaction { export interface Transaction {
id: number; id: number;
date_create: string; date_create: string;
station: string; station?: string;
station_name?: string;
product_name: string; product_name: string;
amount: string; amount: string;
price_real: string; price_real: string;

View File

@ -0,0 +1,17 @@
import { baseAPI } from '@/shared/api/base-api';
import { ReviewFormValues } from '../model/review-form.schema';
export const reviewsAPI = baseAPI.injectEndpoints({
endpoints: (build) => ({
createReview: build.mutation<void, ReviewFormValues>({
query: (body) => ({
url: 'reviews/create',
method: 'POST',
body,
}),
}),
}),
});
export const { useCreateReviewMutation } = reviewsAPI;

View File

@ -27,12 +27,8 @@ import {
} from '@/shared/shadcn-ui/form'; } from '@/shared/shadcn-ui/form';
import { Input } from '@/shared/shadcn-ui/input'; import { Input } from '@/shared/shadcn-ui/input';
import { Textarea } from '@/shared/shadcn-ui/textarea'; import { Textarea } from '@/shared/shadcn-ui/textarea';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/shared/shadcn-ui/tooltip';
import { useCreateReviewMutation } from '../api/reviews.api';
import { ReviewFormValues, reviewSchema } from '../model/review-form.schema'; import { ReviewFormValues, reviewSchema } from '../model/review-form.schema';
export function ReviewForm() { export function ReviewForm() {
@ -40,6 +36,8 @@ export function ReviewForm() {
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [hoveredStar, setHoveredStar] = useState(0); const [hoveredStar, setHoveredStar] = useState(0);
const [createReview] = useCreateReviewMutation();
const form = useForm<ReviewFormValues>({ const form = useForm<ReviewFormValues>({
resolver: zodResolver(reviewSchema), resolver: zodResolver(reviewSchema),
defaultValues: { defaultValues: {
@ -53,7 +51,7 @@ export function ReviewForm() {
setIsSubmitting(true); setIsSubmitting(true);
try { try {
await new Promise((resolve) => setTimeout(resolve, 1500)); await createReview(data);
toast.success( toast.success(
'Спасибо за ваш отзыв! Он будет опубликован после модерации.', 'Спасибо за ваш отзыв! Он будет опубликован после модерации.',

View File

@ -4,14 +4,12 @@ import { Fuel, History, MapPin, Star, Target, Users } from 'lucide-react';
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { Reviews } from '@/app/api-utlities/@types';
import { AboutUsPageData } from '@/app/api-utlities/@types/pages'; import { AboutUsPageData } from '@/app/api-utlities/@types/pages';
import { ReviewForm } from '@/features/review-form/ui'; import { ReviewForm } from '@/features/review-form/ui';
import AnimatedCounter from '@/shared/components/animated-counter'; import AnimatedCounter from '@/shared/components/animated-counter';
import { Container } from '@/shared/components/container'; import { Container } from '@/shared/components/container';
import { Rating } from '@/shared/components/rating';
import { Review } from '@/shared/components/review'; import { Review } from '@/shared/components/review';
import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { useTextController } from '@/shared/language/hooks/use-text-controller';
import { Button } from '@/shared/shadcn-ui/button'; import { Button } from '@/shared/shadcn-ui/button';
@ -296,7 +294,7 @@ export default function AboutPage({ content }: AboutPageProps) {
<Review key={review.id} review={review} /> <Review key={review.id} review={review} />
))} ))}
</div> </div>
<div className='mt-4 flex w-full justify-end'> <div className='mt-4 flex w-full justify-center'>
<ReviewForm /> <ReviewForm />
</div> </div>
</Container> </Container>

View File

@ -199,7 +199,9 @@ export const TransactionsTable = ({
<TableCell> <TableCell>
{format(new Date(transaction.date_create), 'dd.MM.yyyy')} {format(new Date(transaction.date_create), 'dd.MM.yyyy')}
</TableCell> </TableCell>
<TableCell>{transaction.station}</TableCell> <TableCell>
{transaction.station || transaction.station_name}
</TableCell>
<TableCell>{transaction.product_name}</TableCell> <TableCell>{transaction.product_name}</TableCell>
<TableCell className='text-right'> <TableCell className='text-right'>
{transaction.price_real} {transaction.price_real}
@ -268,7 +270,9 @@ export const TransactionsTable = ({
</Pagination> </Pagination>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
<span className='text-sm text-gray-500'>{t('transactions.entries')}</span> <span className='text-sm text-gray-500'>
{t('transactions.entries')}
</span>
<select <select
className='rounded border p-1 text-sm' className='rounded border p-1 text-sm'
value={itemsPerPage} value={itemsPerPage}