This commit is contained in:
Samandar Turgunboyev
2025-11-02 21:49:06 +05:00
parent 68f371db08
commit 9803edc478
7 changed files with 97 additions and 58 deletions

View File

@@ -192,24 +192,22 @@ export interface History {
total_pages: number; total_pages: number;
page_size: number; page_size: number;
current_page: number; current_page: number;
results: [ results: {
{ id: number;
travel_agency: {
custom_id: string;
name: string;
email: string;
phone: string;
};
amount: number;
note: string;
accountant: {
id: number; id: number;
travel_agency: { first_name: string;
custom_id: string; last_name: string;
name: string; role: string;
email: string; };
phone: string; }[];
};
amount: number;
note: string;
accountant: {
id: number;
first_name: string;
last_name: string;
role: string;
};
},
];
}; };
} }

View File

@@ -392,8 +392,11 @@ export default function FinanceDetailUser() {
<div className="flex gap-2"> <div className="flex gap-2">
{companion.participant_pasport_image.map( {companion.participant_pasport_image.map(
(img) => ( (img) => (
<div <a
key={index} key={index}
href={img.image}
target="_blank"
rel="noopener noreferrer"
className="w-20 h-20 rounded-lg bg-slate-700/50 flex items-center justify-center overflow-hidden border border-slate-600/50" className="w-20 h-20 rounded-lg bg-slate-700/50 flex items-center justify-center overflow-hidden border border-slate-600/50"
> >
<img <img
@@ -401,7 +404,7 @@ export default function FinanceDetailUser() {
src={img.image} src={img.image}
className="w-full h-full" className="w-full h-full"
/> />
</div> </a>
), ),
)} )}
</div> </div>

View File

@@ -21,9 +21,16 @@ export function PaymentHistory() {
const { t } = useTranslation(); const { t } = useTranslation();
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const { data, isLoading, isError } = useQuery({ const {
data: history,
isLoading,
isError,
} = useQuery({
queryKey: ["payment-history", page], queryKey: ["payment-history", page],
queryFn: () => getPaymentHistory({ page, page_size: 10 }), queryFn: () => getPaymentHistory({ page, page_size: 10 }),
select(data) {
return data.data;
},
}); });
if (isLoading) if (isLoading)
@@ -33,15 +40,13 @@ export function PaymentHistory() {
</div> </div>
); );
if (isError || !data) if (isError || !history)
return ( return (
<Card className="p-6 text-center"> <Card className="p-6 text-center">
<p className="text-red-500">Xatolik yuz berdi. Qayta urinib koring.</p> <p className="text-red-500">Xatolik yuz berdi. Qayta urinib koring.</p>
</Card> </Card>
); );
const history = data.data;
return ( return (
<Card className="bg-gray-900 text-white"> <Card className="bg-gray-900 text-white">
<CardHeader> <CardHeader>
@@ -60,7 +65,7 @@ export function PaymentHistory() {
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{history.data.results.map((item) => ( {history?.data.results.map((item) => (
<TableRow key={item.id}> <TableRow key={item.id}>
<TableCell>{item.travel_agency.custom_id}</TableCell> <TableCell>{item.travel_agency.custom_id}</TableCell>
<TableCell>{item.travel_agency.name}</TableCell> <TableCell>{item.travel_agency.name}</TableCell>
@@ -68,7 +73,9 @@ export function PaymentHistory() {
<TableCell>{formatPrice(item.amount, true)}</TableCell> <TableCell>{formatPrice(item.amount, true)}</TableCell>
<TableCell>{item.note || "-"}</TableCell> <TableCell>{item.note || "-"}</TableCell>
<TableCell> <TableCell>
{item.accountant.first_name} {item.accountant.last_name} {item.accountant?.first_name || item.accountant?.last_name
? `${item.accountant?.first_name ?? ""} ${item.accountant?.last_name ?? ""}`
: "-"}
</TableCell> </TableCell>
</TableRow> </TableRow>
))} ))}
@@ -78,14 +85,14 @@ export function PaymentHistory() {
{/* Pagination */} {/* Pagination */}
<div className="flex justify-between items-center mt-6"> <div className="flex justify-between items-center mt-6">
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
{t("Sahifa")} {history.data.current_page} /{" "} {t("Sahifa")} {history?.data.current_page} /{" "}
{history.data.total_pages} {history?.data.total_pages}
</p> </p>
<div className="flex gap-2"> <div className="flex gap-2">
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
disabled={!history.data.links.previous} disabled={!history?.data.links.previous}
onClick={() => setPage((p) => Math.max(p - 1, 1))} onClick={() => setPage((p) => Math.max(p - 1, 1))}
> >
<ChevronLeft className="size-6" /> <ChevronLeft className="size-6" />
@@ -93,10 +100,10 @@ export function PaymentHistory() {
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
disabled={!history.data.links.next} disabled={!history?.data.links.next}
onClick={() => onClick={() =>
setPage((p) => setPage((p) =>
Math.min(p + 1, history.data.total_pages || p + 1), Math.min(p + 1, history?.data.total_pages || p + 1),
) )
} }
> >

View File

@@ -245,28 +245,49 @@ const SupportAgency = () => {
{selected.travel_agency_documents && {selected.travel_agency_documents &&
selected.travel_agency_documents.length > 0 ? ( selected.travel_agency_documents.length > 0 ? (
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3"> <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
{selected.travel_agency_documents.map((doc, i) => ( {selected.travel_agency_documents.map((doc, i) => {
<a const isImage = /\.(jpg|jpeg|png|gif|webp)$/i.test(
key={i} doc.file,
href={doc.file} );
target="_blank" const fileName = doc.file.split("/").pop();
rel="noopener noreferrer"
className="group relative aspect-square border-2 border-gray-200 rounded-lg overflow-hidden hover:border-blue-500 transition" return (
> <a
<img key={i}
src={doc.file} href={doc.file}
alt={`Hujjat ${i + 1}`} target="_blank"
className="w-full h-full object-cover" rel="noopener noreferrer"
/> className="group relative aspect-square border-2 border-gray-200 rounded-lg overflow-hidden hover:border-blue-500 transition"
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition flex items-end"> >
<div className="w-full bg-gradient-to-t from-black/70 to-transparent p-2"> {isImage ? (
<span className="text-white text-xs font-medium"> <img
{t("Hujjat")} {i + 1} src={doc.file}
</span> alt={`Hujjat ${i + 1}`}
className="w-full h-full object-cover"
/>
) : (
<div className="w-full h-full flex flex-col items-center justify-center bg-gray-800 text-gray-300">
{/* <img
src="/icons/document-placeholder.png"
alt="Document icon"
className="w-10 h-10 mb-2 opacity-70"
/> */}
<span className="text-xl text-center truncate px-2">
{fileName}
</span>
</div>
)}
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition flex items-end">
<div className="w-full bg-gradient-to-t from-black/70 to-transparent p-2">
<span className="text-white text-xs font-medium">
{t("Hujjat")} {i + 1}
</span>
</div>
</div> </div>
</div> </a>
</a> );
))} })}
</div> </div>
) : ( ) : (
<div className="text-gray-500">{t("Hujjat topilmadi")}</div> <div className="text-gray-500">{t("Hujjat topilmadi")}</div>

View File

@@ -442,7 +442,9 @@ export interface GetDetailTours {
]; ];
tariff: [ tariff: [
{ {
tariff: number; tariff: {
name: string;
};
price: number; price: number;
}, },
]; ];

View File

@@ -278,9 +278,14 @@ export default function TourDetailPage() {
<CheckCircle2 className="w-5 h-5 text-blue-400 mt-1" /> <CheckCircle2 className="w-5 h-5 text-blue-400 mt-1" />
<div> <div>
<p className="text-sm text-gray-400">{t("Tarif")}</p> <p className="text-sm text-gray-400">{t("Tarif")}</p>
<p className="font-semibold text-white capitalize"> {tour.tariff.map((e) => (
{tour.tariff[0]?.tariff} <p
</p> key={e.tariff.name}
className="font-semibold text-white capitalize"
>
{e.tariff.name}
</p>
))}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -471,8 +471,11 @@ const UserDetail = () => {
<div className="flex gap-2"> <div className="flex gap-2">
{companion.participant_pasport_image.map( {companion.participant_pasport_image.map(
(img) => ( (img) => (
<div <a
key={img.id} key={img.id}
href={img.image}
target="_blank"
rel="noopener noreferrer"
className="w-20 h-20 rounded-lg bg-slate-700/50 flex items-center justify-center overflow-hidden border border-slate-600/50" className="w-20 h-20 rounded-lg bg-slate-700/50 flex items-center justify-center overflow-hidden border border-slate-600/50"
> >
<img <img
@@ -480,7 +483,7 @@ const UserDetail = () => {
src={img.image} src={img.image}
className="w-full h-full" className="w-full h-full"
/> />
</div> </a>
), ),
)} )}
</div> </div>