bug fix
This commit is contained in:
50
src/widgets/welcome/lib/api.ts
Normal file
50
src/widgets/welcome/lib/api.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import httpClient from "@/shared/config/api/httpClient";
|
||||
import { GET_ME } from "@/shared/config/api/URLs";
|
||||
|
||||
interface GetMe {
|
||||
status: boolean;
|
||||
data: {
|
||||
id: number;
|
||||
last_login: string;
|
||||
is_superuser: boolean;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
is_staff: boolean;
|
||||
is_active: boolean;
|
||||
date_joined: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
username: string;
|
||||
avatar: string;
|
||||
validated_at: string;
|
||||
role: string;
|
||||
travel_agency: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface GetAllParticipantData {
|
||||
status: boolean;
|
||||
data: {
|
||||
links: {
|
||||
previous: string;
|
||||
next: string;
|
||||
};
|
||||
total_items: number;
|
||||
total_pages: number;
|
||||
page_size: number;
|
||||
current_page: number;
|
||||
results: {
|
||||
id: number;
|
||||
first_name: string;
|
||||
gender: "male" | "female";
|
||||
last_name: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export const User_Api = {
|
||||
async getMe() {
|
||||
const res = await httpClient.get<GetMe>(GET_ME);
|
||||
return res;
|
||||
},
|
||||
};
|
||||
28
src/widgets/welcome/lib/data.ts
Normal file
28
src/widgets/welcome/lib/data.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import httpClient from "@/shared/config/api/httpClient";
|
||||
import { UPDATE_USERS } from "@/shared/config/api/URLs";
|
||||
|
||||
export const Auth_Api = {
|
||||
async updateUser({
|
||||
first_name,
|
||||
last_name,
|
||||
avatar,
|
||||
}: {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
avatar?: File;
|
||||
}) {
|
||||
const formData = new FormData();
|
||||
formData.append("first_name", first_name);
|
||||
formData.append("last_name", last_name);
|
||||
if (avatar) {
|
||||
formData.append("avatar", avatar);
|
||||
}
|
||||
|
||||
const res = await httpClient.patch(UPDATE_USERS, formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
return res;
|
||||
},
|
||||
};
|
||||
11
src/widgets/welcome/lib/form.ts
Normal file
11
src/widgets/welcome/lib/form.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import z from "zod";
|
||||
|
||||
export const welcomeForm = z.object({
|
||||
firstName: z.string().min(1, { message: "Majburiy maydon" }),
|
||||
lastName: z.string().min(1, { message: "Majburiy maydon" }),
|
||||
});
|
||||
|
||||
export const editUserName = z.object({
|
||||
firstName: z.string().min(1, { message: "Majburiy maydon" }),
|
||||
lastName: z.string().min(1, { message: "Majburiy maydon" }),
|
||||
});
|
||||
15
src/widgets/welcome/lib/hook.ts
Normal file
15
src/widgets/welcome/lib/hook.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface WelcomeState {
|
||||
openModal: boolean;
|
||||
setOpenModal: (openModal: boolean) => void;
|
||||
openModalMobile: boolean;
|
||||
setOpenModalMobile: (openModal: boolean) => void;
|
||||
}
|
||||
|
||||
export const useWelcomeStore = create<WelcomeState>((set) => ({
|
||||
openModal: false,
|
||||
setOpenModal: (openModal) => set({ openModal }),
|
||||
openModalMobile: false,
|
||||
setOpenModalMobile: (openModalMobile) => set({ openModalMobile }),
|
||||
}));
|
||||
@@ -1,26 +1,210 @@
|
||||
import LangToggle from "@/widgets/lang-toggle/ui/lang-toggle";
|
||||
import ModeToggle from "@/widgets/theme-toggle/ui/theme-toggle";
|
||||
import GitHubButton from "react-github-btn";
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/shared/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} from "@/shared/ui/form";
|
||||
import { Input } from "@/shared/ui/input";
|
||||
import { Label } from "@/shared/ui/label";
|
||||
import { Auth_Api } from "@/widgets/welcome/lib/data";
|
||||
import { welcomeForm } from "@/widgets/welcome/lib/form";
|
||||
import { useWelcomeStore } from "@/widgets/welcome/lib/hook";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import Drawer from "@mui/material/Drawer";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { AxiosError } from "axios";
|
||||
import clsx from "clsx";
|
||||
import { LoaderCircle, XIcon } from "lucide-react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import z from "zod";
|
||||
|
||||
const Welcome = () => {
|
||||
return (
|
||||
<div className="custom-container h-screen rounded-2xl flex items-center justify-center">
|
||||
<div className="flex flex-col gap-2 items-center">
|
||||
<GitHubButton
|
||||
href="https://github.com/fiasuz/fias-ui"
|
||||
data-color-scheme="no-preference: light; light: light; dark: dark;"
|
||||
data-size="large"
|
||||
data-show-count="true"
|
||||
aria-label="Star fiasuz/fias-ui on GitHub"
|
||||
const { openModal: open, setOpenModal: setOpen } = useWelcomeStore();
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const form = useForm<z.infer<typeof welcomeForm>>({
|
||||
resolver: zodResolver(welcomeForm),
|
||||
defaultValues: {
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
},
|
||||
});
|
||||
const isMobile = useMediaQuery("(max-width:1024px)");
|
||||
|
||||
const { mutate, isPending } = useMutation({
|
||||
mutationFn: ({
|
||||
first_name,
|
||||
last_name,
|
||||
}: {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
}) => {
|
||||
return Auth_Api.updateUser({ first_name, last_name });
|
||||
},
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries();
|
||||
setOpen(false);
|
||||
},
|
||||
onError(error: AxiosError<{ non_field_errors: [string] }>) {
|
||||
toast.error(t("Xatolik yuz berdi"), {
|
||||
icon: null,
|
||||
description: error.name,
|
||||
position: "bottom-right",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function onSubmit(values: z.infer<typeof welcomeForm>) {
|
||||
mutate({
|
||||
first_name: values.firstName,
|
||||
last_name: values.lastName,
|
||||
});
|
||||
}
|
||||
|
||||
const formContent = (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 w-full">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="firstName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<Label className="text-xl font-semibold text-[#212122]">
|
||||
{t("Имя")}
|
||||
</Label>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={t("Введите имя")}
|
||||
className="h-[60px] px-4 font-medium !text-lg rounded-xl text-black"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lastName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<Label className="text-xl font-semibold text-[#212122]">
|
||||
{t("Фамилия")}
|
||||
</Label>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={t("Введите фамилию")}
|
||||
className="h-[60px] px-4 font-medium !text-lg rounded-xl text-black max-lg:w-full"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
className="px-14 py-8 rounded-4xl text-lg font-medium cursor-pointer bg-[#1764FC] hover:bg-[#1764FC] max-lg:w-full max-lg:mt-10"
|
||||
>
|
||||
Star
|
||||
</GitHubButton>
|
||||
<div className="flex flex-row gap-2">
|
||||
<ModeToggle />
|
||||
<LangToggle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isPending ? (
|
||||
<LoaderCircle className="animate-spin" />
|
||||
) : (
|
||||
t("Сохранить")
|
||||
)}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isMobile ? (
|
||||
<Dialog open={open}>
|
||||
<DialogContent
|
||||
className="rounded-4xl !max-w-3xl"
|
||||
showCloseButton={false}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle
|
||||
className={clsx("flex justify-between w-full items-center")}
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<p className="text-2xl">{t("Давайте познакомимся!")}</p>
|
||||
<p className="w-[80%] text-[#646465] font-medium">
|
||||
{t(
|
||||
"Чтобы завершить регистрацию, пожалуйста, укажите ваше имя",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
disabled
|
||||
className="rounded-full p-6 h-12 w-12 cursor-pointer"
|
||||
>
|
||||
<XIcon className="w-26 h-26" />
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogTitle>
|
||||
<DialogDescription className="flex flex-col justify-center items-center gap-8 mt-5">
|
||||
{formContent}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
) : (
|
||||
<Drawer
|
||||
anchor="bottom"
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderTopLeftRadius: 16,
|
||||
borderTopRightRadius: 16,
|
||||
width: "100vw",
|
||||
height: "auto",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
p: 2,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-3xl font-semibold">
|
||||
{t("Давайте познакомимся!")}
|
||||
</p>
|
||||
<p className="w-[80%] text-[#646465] font-medium">
|
||||
{t("Чтобы завершить регистрацию, пожалуйста, укажите ваше имя")}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
disabled
|
||||
className="rounded-full p-6 h-12 w-12 cursor-pointer"
|
||||
>
|
||||
<XIcon className="w-26 h-26" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-5">{formContent}</div>
|
||||
</Drawer>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user