user update price type
This commit is contained in:
@@ -43,4 +43,15 @@ export const user_api = {
|
||||
const res = await httpClient.post(API_URLS.PasswordSet(id), body);
|
||||
return res;
|
||||
},
|
||||
|
||||
async price_type_set({
|
||||
body,
|
||||
id,
|
||||
}: {
|
||||
id: string | number;
|
||||
body: { ids: number[] };
|
||||
}) {
|
||||
const res = await httpClient.post(API_URLS.PriceTypeSet(id), body);
|
||||
return res;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface UserData {
|
||||
short_name: string;
|
||||
created_at: string;
|
||||
password_set: boolean;
|
||||
price_types: number[];
|
||||
}
|
||||
|
||||
export interface UserListRes {
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import price_type_api from "@/features/price-type/lib/api";
|
||||
import { user_api } from "@/features/users/lib/api";
|
||||
import type { UserData } from "@/features/users/lib/data";
|
||||
import formatDate from "@/shared/lib/formatDate";
|
||||
import { cn } from "@/shared/lib/utils";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/shared/ui/command";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -19,6 +28,7 @@ import {
|
||||
} from "@/shared/ui/form";
|
||||
import { Input } from "@/shared/ui/input";
|
||||
import { Label } from "@/shared/ui/label";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/shared/ui/popover";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -28,10 +38,10 @@ import {
|
||||
TableRow,
|
||||
} from "@/shared/ui/table";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import type { AxiosError } from "axios";
|
||||
import { Edit } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Check, ChevronsUpDown, Edit } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import z from "zod";
|
||||
@@ -49,7 +59,28 @@ interface UserListProps {
|
||||
export function UserCard({ users }: UserListProps) {
|
||||
const [edit, setEdit] = useState<number | string | null>(null);
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [openPriceId, setOpenPriceId] = useState<number | null>(null);
|
||||
const queryClient = useQueryClient();
|
||||
const [values, setValues] = useState<Record<string | number, string[]>>({});
|
||||
|
||||
const { data } = useQuery({
|
||||
queryKey: ["price_type"],
|
||||
queryFn: () => price_type_api.list(),
|
||||
select(data) {
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const initialValues: Record<string | number, string[]> = {};
|
||||
users.forEach((user) => {
|
||||
if (user.price_types) {
|
||||
initialValues[user.id] = user.price_types.map((id) => id.toString());
|
||||
}
|
||||
});
|
||||
|
||||
setValues(initialValues);
|
||||
}, [users]);
|
||||
|
||||
const form = useForm<z.infer<typeof passwordSet>>({
|
||||
resolver: zodResolver(passwordSet),
|
||||
@@ -87,6 +118,52 @@ export function UserCard({ users }: UserListProps) {
|
||||
},
|
||||
});
|
||||
|
||||
const { mutate: price_type_set } = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
body,
|
||||
}: {
|
||||
id: number | string;
|
||||
body: { ids: number[] };
|
||||
}) => user_api.price_type_set({ body, id }),
|
||||
onSuccess: () => {
|
||||
setOpenPriceId(null);
|
||||
queryClient.refetchQueries({ queryKey: ["user_list"] });
|
||||
toast.success("Narx qo'yildi", {
|
||||
richColors: true,
|
||||
position: "top-center",
|
||||
});
|
||||
},
|
||||
onError: (err: AxiosError) => {
|
||||
const errData = (err.response?.data as { data: string }).data;
|
||||
const errMessage = (err.response?.data as { message: string }).message;
|
||||
|
||||
toast.error(errData || errMessage || "Xatolik yuz berdi", {
|
||||
richColors: true,
|
||||
position: "top-center",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const toggleValue = (userId: string | number, value: string) => {
|
||||
let newUserValues: string[] = [];
|
||||
|
||||
setValues((prev) => {
|
||||
const userValues = prev[userId] || [];
|
||||
newUserValues = userValues.includes(value)
|
||||
? userValues.filter((v) => v !== value)
|
||||
: [...userValues, value];
|
||||
return { ...prev, [userId]: newUserValues };
|
||||
});
|
||||
const currentUserValues = values[userId] || [];
|
||||
const nextUserValues = currentUserValues.includes(value)
|
||||
? currentUserValues.filter((v) => v !== value)
|
||||
: [...currentUserValues, value];
|
||||
|
||||
setValues((prev) => ({ ...prev, [userId]: nextUserValues }));
|
||||
price_type_set({ body: { ids: nextUserValues.map(Number) }, id: userId });
|
||||
};
|
||||
|
||||
function onSubmit(value: z.infer<typeof passwordSet>) {
|
||||
if (edit) {
|
||||
mutate({ body: { password: value.password }, id: edit });
|
||||
@@ -102,11 +179,14 @@ export function UserCard({ users }: UserListProps) {
|
||||
<TableHead>To'liq ism</TableHead>
|
||||
<TableHead>Username</TableHead>
|
||||
<TableHead>Ro'yxatdan o'tgan</TableHead>
|
||||
<TableHead>Biriktirilgan narx</TableHead>
|
||||
<TableHead className="text-right">Amallar</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{users.map((user) => (
|
||||
{users.map((user) => {
|
||||
const userValues = values[user.id] || [];
|
||||
return (
|
||||
<TableRow key={user.id} className="hover:bg-muted/50">
|
||||
<TableCell className="font-medium">{user.id}</TableCell>
|
||||
<TableCell>
|
||||
@@ -115,7 +195,9 @@ export function UserCard({ users }: UserListProps) {
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span className="text-muted-foreground">@{user.username}</span>
|
||||
<span className="text-muted-foreground">
|
||||
@{user.username}
|
||||
</span>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
@@ -123,6 +205,71 @@ export function UserCard({ users }: UserListProps) {
|
||||
{formatDate.format(user.created_at, "DD-MM-YYYY")}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Popover
|
||||
open={openPriceId === user.id}
|
||||
onOpenChange={(isOpen) =>
|
||||
setOpenPriceId(isOpen ? user.id : null)
|
||||
}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openPriceId === user.id}
|
||||
className="w-[200px] justify-between cursor-pointer"
|
||||
>
|
||||
<span className="truncate">
|
||||
{userValues.length > 0
|
||||
? userValues
|
||||
.map(
|
||||
(id) =>
|
||||
data?.find(
|
||||
(item) => item.id.toString() === id,
|
||||
)?.name,
|
||||
)
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
: "Narxni tanlang"}
|
||||
</span>
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent className="w-[200px] p-0" align="start">
|
||||
<Command>
|
||||
<CommandList>
|
||||
<CommandEmpty>Topilmadi.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{data?.map((option) => {
|
||||
const isSelected = userValues.includes(
|
||||
option.id.toString(),
|
||||
);
|
||||
|
||||
return (
|
||||
<CommandItem
|
||||
key={option.id}
|
||||
onSelect={() =>
|
||||
toggleValue(user.id, option.id.toString())
|
||||
}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
isSelected ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{option.name}
|
||||
</CommandItem>
|
||||
);
|
||||
})}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<Dialog
|
||||
open={open && edit === user.id}
|
||||
@@ -202,7 +349,8 @@ export function UserCard({ users }: UserListProps) {
|
||||
</Dialog>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
@@ -47,4 +47,6 @@ export const API_URLS = {
|
||||
Update_Pyment_Type: (id: number) =>
|
||||
`${API_V}admin/product/${id}/update_payment_type/`,
|
||||
Import_Balance: `${API_V}admin/product/import/balance/`,
|
||||
PriceTypeSet: (id: number | string) =>
|
||||
`${API_V}admin/user/${id}/set_price_type/`,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user