feat: implement pluralization for client and session counts in ClientsPage and SessionsPage
This commit is contained in:
+13
-15
@@ -4,16 +4,17 @@ import SpinIcon from "../components/icons/SpinIcon";
|
|||||||
import MultySelect from "../components/MultySelect";
|
import MultySelect from "../components/MultySelect";
|
||||||
import SearchInput from "../components/SearchInput";
|
import SearchInput from "../components/SearchInput";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useDebounce } from "@uidotdev/usehooks";
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { IUser } from "../types/User";
|
import { IUser } from "../types/User";
|
||||||
import api from "../utils/api";
|
import api from "../utils/api";
|
||||||
|
import { Client } from "../types/Client";
|
||||||
|
import pluralize from "../utils/pluralize";
|
||||||
|
|
||||||
function ClientsPage() {
|
function ClientsPage() {
|
||||||
const [limit, setLimit] = useState(10);
|
const [limit, setLimit] = useState(10);
|
||||||
const [search, setSearch] = useState<string | null>(null);
|
const [search, setSearch] = useState<string | null>(null);
|
||||||
|
|
||||||
const debouncedSearch = useDebounce(search, 500);
|
// const debouncedSearch = useDebounce(search, 500);
|
||||||
|
|
||||||
const { data: me } = useQuery({
|
const { data: me } = useQuery({
|
||||||
queryKey: ["me"],
|
queryKey: ["me"],
|
||||||
@@ -22,13 +23,7 @@ function ClientsPage() {
|
|||||||
|
|
||||||
const { data: clients, isLoading } = useQuery({
|
const { data: clients, isLoading } = useQuery({
|
||||||
queryKey: ["clients"],
|
queryKey: ["clients"],
|
||||||
queryFn: () => api.get("clients").json<IUser[]>(),
|
queryFn: () => api.get("clients").json<Client[]>(),
|
||||||
enabled: !!me,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: count } = useQuery({
|
|
||||||
queryKey: ["clients", "count", debouncedSearch],
|
|
||||||
queryFn: () => api.get(`sessions/count?clients`).json<number>(),
|
|
||||||
enabled: !!me,
|
enabled: !!me,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,7 +72,10 @@ function ClientsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<p className="caption-m font-medium opacity-40">
|
<p className="caption-m font-medium opacity-40">
|
||||||
Найдено {count} клиентов
|
Найдено{" "}
|
||||||
|
{clients?.length
|
||||||
|
? pluralize(clients?.length, "клиент")
|
||||||
|
: "0 клиентов"}
|
||||||
</p>
|
</p>
|
||||||
<button className="flex gap-[0.278vw] items-center" onClick={reset}>
|
<button className="flex gap-[0.278vw] items-center" onClick={reset}>
|
||||||
<div className="size-[1.111vw] text-[#7D7D7D]">
|
<div className="size-[1.111vw] text-[#7D7D7D]">
|
||||||
@@ -96,9 +94,9 @@ function ClientsPage() {
|
|||||||
<SpinIcon />
|
<SpinIcon />
|
||||||
</div>
|
</div>
|
||||||
) : clients?.length ? (
|
) : clients?.length ? (
|
||||||
clients?.map(({ fullname }) => (
|
clients?.map(({ name }) => (
|
||||||
<div key={fullname} className="space-y-[0.833vw]">
|
<div key={name} className="space-y-[0.833vw]">
|
||||||
<p className="caption-m font-medium opacity-40">{fullname}</p>
|
<p className="caption-m font-medium opacity-40">{name}</p>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@@ -113,13 +111,13 @@ function ClientsPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!count && clients?.length === 0 && (
|
{!!clients?.length && clients?.length === 0 && (
|
||||||
<Button
|
<Button
|
||||||
size="large"
|
size="large"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
onClick={() => setLimit((prev) => prev + 10)}
|
onClick={() => setLimit((prev) => prev + 10)}
|
||||||
disabled={!!count && limit >= count}
|
disabled={!!clients?.length && limit >= clients.length}
|
||||||
>
|
>
|
||||||
Показать еще
|
Показать еще
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import Button from "../components/Button";
|
|||||||
import SearchInput from "../components/SearchInput";
|
import SearchInput from "../components/SearchInput";
|
||||||
import CloseIcon from "../components/icons/CloseIcon";
|
import CloseIcon from "../components/icons/CloseIcon";
|
||||||
import SpinIcon from "../components/icons/SpinIcon";
|
import SpinIcon from "../components/icons/SpinIcon";
|
||||||
|
import pluralize from "../utils/pluralize";
|
||||||
|
|
||||||
function SessionsPage() {
|
function SessionsPage() {
|
||||||
const [limit, setLimit] = useState(10);
|
const [limit, setLimit] = useState(10);
|
||||||
@@ -118,7 +119,7 @@ function SessionsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<p className="caption-m font-medium opacity-40">
|
<p className="caption-m font-medium opacity-40">
|
||||||
Найдено {count} сеансов
|
Найдено {count ? pluralize(count, "сеанс") : "0 сеансов"}
|
||||||
</p>
|
</p>
|
||||||
<button className="flex gap-[0.278vw] items-center" onClick={reset}>
|
<button className="flex gap-[0.278vw] items-center" onClick={reset}>
|
||||||
<div className="size-[1.111vw] text-[#7D7D7D]">
|
<div className="size-[1.111vw] text-[#7D7D7D]">
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
function pluralize(count: number, word: "клиент" | "сеанс"): string {
|
||||||
|
const cases = [2, 0, 1, 1, 1, 2];
|
||||||
|
const index =
|
||||||
|
count % 100 > 4 && count % 100 < 20
|
||||||
|
? 2
|
||||||
|
: cases[count % 10 < 5 ? count % 10 : 5];
|
||||||
|
|
||||||
|
const specialWords: Record<string, string[]> = {
|
||||||
|
клиент: ["клиент", "клиента", "клиентов"],
|
||||||
|
сеанс: ["сеанс", "сеанса", "сеансов"],
|
||||||
|
};
|
||||||
|
|
||||||
|
return `${count} ${specialWords[word][index]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default pluralize;
|
||||||
Reference in New Issue
Block a user