From d4788c7cb250aa16ec9095f2462b79cff3ba8579 Mon Sep 17 00:00:00 2001 From: Samandar Turgunboyev Date: Mon, 1 Dec 2025 13:23:40 +0500 Subject: [PATCH] ui edit --- src/features/district/lib/data-table.tsx | 2 +- src/features/district/ui/district.tsx | 10 +- src/features/doctor/lib/data-table.tsx | 2 +- src/features/home/ui/Home.tsx | 63 +++--- src/features/location/ui/MyLocation.tsx | 2 +- src/features/object/lib/data-table.tsx | 2 +- src/features/object/ui/ObjectList.tsx | 21 +- src/features/phamarcy/ui/PharmacyList.tsx | 4 +- src/features/plan-tour/ui/PlanTour.tsx | 76 ++++--- .../specification/ui/HistoryListPage.tsx | 6 +- src/features/tour-plan/lib/data-table.tsx | 2 +- src/shared/ui/added-button.tsx | 2 +- src/shared/ui/sheet.tsx | 21 +- .../dashboard-layout/ui/DashboardLayout.tsx | 197 +++++++++++++----- vite.config.ts | 2 +- 15 files changed, 270 insertions(+), 142 deletions(-) diff --git a/src/features/district/lib/data-table.tsx b/src/features/district/lib/data-table.tsx index 71ec146..b5e2948 100644 --- a/src/features/district/lib/data-table.tsx +++ b/src/features/district/lib/data-table.tsx @@ -69,7 +69,7 @@ export function DataTableDistruct({ ) : ( - No results. + Tuman mavjud emas )} diff --git a/src/features/district/ui/district.tsx b/src/features/district/ui/district.tsx index 4bc97fb..f083b51 100644 --- a/src/features/district/ui/district.tsx +++ b/src/features/district/ui/district.tsx @@ -191,12 +191,8 @@ export default function District() { return ( -
+ <>
-
-

Tumanlar

-

Tumanlarni boshqarish

-
form.reset({ name: "" })} /> @@ -260,7 +256,7 @@ export default function District() {
-
+

Tumanlar ro‘yxati

{/* Loading state */} @@ -282,7 +278,7 @@ export default function District() {

Tumanlar mavjud emas

)}
-
+ diff --git a/src/features/doctor/lib/data-table.tsx b/src/features/doctor/lib/data-table.tsx index 5eaec97..99857d7 100644 --- a/src/features/doctor/lib/data-table.tsx +++ b/src/features/doctor/lib/data-table.tsx @@ -69,7 +69,7 @@ export function DataTable({ ) : ( - No results. + Shifokor mavjud emas )} diff --git a/src/features/home/ui/Home.tsx b/src/features/home/ui/Home.tsx index bd5444e..58c23e8 100644 --- a/src/features/home/ui/Home.tsx +++ b/src/features/home/ui/Home.tsx @@ -4,16 +4,18 @@ import { useMutation } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import clsx from "clsx"; import { + Banknote, Calendar, - Clipboard, FileText, - HomeIcon, - Layers, List, - MapPin, - Syringe, + Loader2, + MapPinCheck, + MapPinHouse, + MapPinned, + Pill, User, } from "lucide-react"; +import { useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import { toast } from "sonner"; @@ -31,7 +33,7 @@ const navItems: NavItem[] = [ id: "lokatsiya", title: "Lokatsiya jo'natish", link: "/location", - icon: , + icon: , description: "Manzilni jo'natish", featured: true, }, @@ -56,12 +58,14 @@ const navItems: NavItem[] = [ export default function Home() { const featuredItems = navItems.filter((item) => item.featured); const router = useNavigate(); + const [locationLoad, setLocationLoad] = useState(false); const { mutate } = useMutation({ mutationFn: (body: SendLocation) => location_api.send_loaction(body), onSuccess: () => { toast.success("Lokatsiya jo'natildi"); router("/location"); + setLocationLoad(false); }, onError: (error: AxiosError) => { const data = error.response?.data as { message?: string }; @@ -77,6 +81,7 @@ export default function Home() { name: string[]; }; }; + setLocationLoad(false); const message = Array.isArray(errorName.data?.name) && errorName.data.name.length @@ -92,6 +97,7 @@ export default function Home() { }); const handleLocationClick = () => { + setLocationLoad(true); navigator.geolocation.getCurrentPosition( (pos) => { mutate({ @@ -125,41 +131,48 @@ export default function Home() {

Asosiy

-
+
{featuredItems.map((item) => { const isLocation = item.id === "lokatsiya"; + const specification = item.id === "spetsifikatsiya"; + const tourPlan = item.id === "tour_plan"; return (
{!isLocation ? ( - + ) : null}
- {item.icon} + {isLocation && locationLoad ? ( + + ) : ( + item.icon + )}
-

+

{item.title}

@@ -210,7 +223,7 @@ export default function Home() {

- +

Tuman

@@ -218,7 +231,7 @@ export default function Home() {
- +

Obyekt @@ -242,7 +255,7 @@ export default function Home() {
- +

Dorixona @@ -257,10 +270,10 @@ export default function Home() { >
- +

- Hisobotlar + To'lovlar

diff --git a/src/features/location/ui/MyLocation.tsx b/src/features/location/ui/MyLocation.tsx index 120418f..8448edb 100644 --- a/src/features/location/ui/MyLocation.tsx +++ b/src/features/location/ui/MyLocation.tsx @@ -346,7 +346,7 @@ const MyLocation: React.FC = () => { colSpan={columns.length} className="h-24 text-center" > - No results. + Hech qanday lokatsiya jo'natilmagan )} diff --git a/src/features/object/lib/data-table.tsx b/src/features/object/lib/data-table.tsx index 8f26221..980f1b2 100644 --- a/src/features/object/lib/data-table.tsx +++ b/src/features/object/lib/data-table.tsx @@ -69,7 +69,7 @@ export function DataTableObject({ ) : ( - No results. + Obyekt mavjud emas )} diff --git a/src/features/object/ui/ObjectList.tsx b/src/features/object/ui/ObjectList.tsx index 4139749..10a59c0 100644 --- a/src/features/object/ui/ObjectList.tsx +++ b/src/features/object/ui/ObjectList.tsx @@ -9,6 +9,7 @@ import { DialogHeader, DialogTitle, } from "@/shared/ui/dialog"; +import { Skeleton } from "@/shared/ui/skeleton"; import { DashboardLayout } from "@/widgets/dashboard-layout/ui/DashboardLayout"; import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; @@ -80,16 +81,22 @@ const ObjectList = () => {

)} - {!isLoading && !isError && objects && objects.length > 0 && ( + {isLoading ? ( +
+ {[1, 2, 3].map((i) => ( + + ))} +
+ ) : isError ? ( +

+ Tumanlar yuklanmadi. Qayta urinib ko‘ring. +

+ ) : objects ? (
- )} - - {!isLoading && !isError && objects && objects.length === 0 && ( -
- Hech qanday obyekt topilmadi. -
+ ) : ( +

Tumanlar mavjud emas

)}

diff --git a/src/features/phamarcy/ui/PharmacyList.tsx b/src/features/phamarcy/ui/PharmacyList.tsx index a38a994..55eaaac 100644 --- a/src/features/phamarcy/ui/PharmacyList.tsx +++ b/src/features/phamarcy/ui/PharmacyList.tsx @@ -46,8 +46,8 @@ const PharmacyList = () => { )} {!isLoading && !isError && data?.length === 0 && ( -
-

Hech qanday dorixona topilmadi

+
+

Dorixona mavjud emas

)} diff --git a/src/features/plan-tour/ui/PlanTour.tsx b/src/features/plan-tour/ui/PlanTour.tsx index 1a55f83..b6f4fd6 100644 --- a/src/features/plan-tour/ui/PlanTour.tsx +++ b/src/features/plan-tour/ui/PlanTour.tsx @@ -92,10 +92,10 @@ const PlanTour = () => {

- Oylik hisobotlar + Oylik to'lovlar

- Dorixonalar uchun oylik summalarni boshqaring + Dorixonalar uchun oylik to'lovlarni boshqaring

{isLoading && ( @@ -110,40 +110,48 @@ const PlanTour = () => {
)} - - - - - Oy tanlash - - + {!isLoading && !isError && data && data.length === 0 ? ( +
+

Hech qanday to'lovlar yo'q

+
+ ) : ( + <> + + + + + Oy tanlash + + - -
- {availableMonths().map((month) => ( - - ))} -
-
-
+ +
+ {availableMonths().map((month) => ( + + ))} +
+
+
- + + + )}
); diff --git a/src/features/specification/ui/HistoryListPage.tsx b/src/features/specification/ui/HistoryListPage.tsx index b71d21b..90bc37f 100644 --- a/src/features/specification/ui/HistoryListPage.tsx +++ b/src/features/specification/ui/HistoryListPage.tsx @@ -125,9 +125,9 @@ export function HistoryListPage() {
)) ) : ( -

- {"Hozircha ma'lumot yo‘q."} -

+
+

{"Hozircha ma'lumot yo‘q."}

+
)}
diff --git a/src/features/tour-plan/lib/data-table.tsx b/src/features/tour-plan/lib/data-table.tsx index 9207162..e948bf8 100644 --- a/src/features/tour-plan/lib/data-table.tsx +++ b/src/features/tour-plan/lib/data-table.tsx @@ -65,7 +65,7 @@ export function DataTable({ columns, data }: DataTableProps) { ) : ( - No results. + Bu oy uchun tur plan mavjud emas )} diff --git a/src/shared/ui/added-button.tsx b/src/shared/ui/added-button.tsx index b731b6a..e092f98 100644 --- a/src/shared/ui/added-button.tsx +++ b/src/shared/ui/added-button.tsx @@ -18,7 +18,7 @@ const rippleVariants = { const AddedButton: React.FC = ({ onClick }) => { return ( -
+
{[0.5, 1, 1.5].map((delay, i) => ( & { @@ -72,10 +73,12 @@ function SheetContent({ {...props} > {children} - - - Close - + {closedButton && ( + + + Close + + )} ); @@ -129,11 +132,11 @@ function SheetDescription({ export { Sheet, - SheetTrigger, SheetClose, SheetContent, - SheetHeader, - SheetFooter, - SheetTitle, SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, }; diff --git a/src/widgets/dashboard-layout/ui/DashboardLayout.tsx b/src/widgets/dashboard-layout/ui/DashboardLayout.tsx index 4811ff9..af76fd2 100644 --- a/src/widgets/dashboard-layout/ui/DashboardLayout.tsx +++ b/src/widgets/dashboard-layout/ui/DashboardLayout.tsx @@ -1,22 +1,30 @@ import Logo from "@/assets/logo.png"; +import { location_api, type SendLocation } from "@/features/home/lib/api"; import { cn } from "@/shared/lib/utils"; import { Button } from "@/shared/ui/button"; -import { Sheet, SheetContent } from "@/shared/ui/sheet"; +import { Sheet, SheetClose, SheetContent } from "@/shared/ui/sheet"; +import { useMutation } from "@tanstack/react-query"; +import type { AxiosError } from "axios"; import { - Building, - Building2, + Banknote, Calendar, ChevronLeft, FileText, - MapPin, + Home, + List, + Loader2, + MapPinCheck, + MapPinHouse, + MapPinned, Menu, - Navigation, - Truck, + Pill, User, + X, } from "lucide-react"; import { useState, type ReactNode } from "react"; -import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import { toast } from "sonner"; interface NavItem { title: string; @@ -25,24 +33,63 @@ interface NavItem { } const navItems: NavItem[] = [ - { title: "Reja", href: "/plan", icon: Calendar }, - { title: "Tuman", href: "/district", icon: MapPin }, - { title: "Obyekt", href: "/object", icon: Building2 }, - { title: "Shifokor", href: "/physician", icon: User }, - { title: "Dorixona", href: "/pharmacy", icon: Building }, - { title: "Tur Plan", href: "/type-plan", icon: Truck }, - { title: "Lokatsiya", href: "/location", icon: Navigation }, + { title: "Asosiy sahifa", href: "/", icon: Home }, + { title: "Lokatsiya jo'natish", href: "/location", icon: MapPinCheck }, { title: "Spetsifikatsiya", href: "/specification", icon: FileText }, + { title: "Tur Plan", href: "/tour-plan", icon: List }, + { title: "Reja", href: "/plan", icon: Calendar }, + { title: "Tuman", href: "/district", icon: MapPinned }, + { title: "Obyekt", href: "/object", icon: MapPinHouse }, + { title: "Shifokor", href: "/physician", icon: User }, + { title: "Dorixona", href: "/pharmacy", icon: Pill }, + { title: "To'lovlar", href: "/type-plan", icon: Banknote }, ]; export function DashboardLayout({ children }: { children: ReactNode }) { const location = useLocation(); const pathname = location.pathname; const router = useNavigate(); - const params = useParams(); - const locale = params.locale as string; const [sidebarOpen, setSidebarOpen] = useState(false); + const [locationLoad, setLocationLoad] = useState(false); + + const { mutate: sendLocation } = useMutation({ + mutationFn: (body: SendLocation) => location_api.send_loaction(body), + onSuccess: () => { + toast.success("Lokatsiya jo'natildi"); + setLocationLoad(false); + router("/location"); + }, + onError: (error: AxiosError) => { + const data = error.response?.data as { message?: string }; + toast.error(data?.message || "Xatolik yuz berdi"); + setLocationLoad(false); + }, + }); + + const handleSidebarLocationClick = () => { + setLocationLoad(true); + + navigator.geolocation.getCurrentPosition( + (pos) => { + sendLocation({ + latitude: pos.coords.latitude, + longitude: pos.coords.longitude, + }); + }, + (err) => { + toast.error("Lokatsiya olishda xatolik"); + console.error(err); + setLocationLoad(false); + }, + { + enableHighAccuracy: true, + timeout: 15000, + maximumAge: 0, + }, + ); + }; + return (
{/* Sidebar - Desktop */} @@ -55,21 +102,46 @@ export function DashboardLayout({ children }: { children: ReactNode }) {
    {navItems.map((item) => { const Icon = item.icon; - const isActive = pathname?.includes(item.href); + const isActive = + item.href === "/" + ? pathname === "/" + : pathname.startsWith(item.href); + + const isLocationItem = item.href === "/location"; + return (
  • - - - {item.title} - + {isLocationItem ? ( + + ) : ( + + + {item.title} + + )}
  • ); })} @@ -105,30 +177,59 @@ export function DashboardLayout({ children }: { children: ReactNode }) { {/* Mobile Sidebar */} - -
    - logo + +
    + logo + + +
    -