feat: health check seo preview
This commit is contained in:
@@ -1,4 +1,10 @@
|
|||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogFooter,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
interface SeoPreviewData {
|
interface SeoPreviewData {
|
||||||
@@ -30,17 +36,37 @@ export default function SeoPreview({
|
|||||||
title = "SEO Preview",
|
title = "SEO Preview",
|
||||||
}: SeoPreviewProps) {
|
}: SeoPreviewProps) {
|
||||||
const previewUrl = url || "#";
|
const previewUrl = url || "#";
|
||||||
|
|
||||||
|
const hasSeoData =
|
||||||
|
!!previewData?.seo &&
|
||||||
|
!!(
|
||||||
|
previewData.seo.ogImage ||
|
||||||
|
previewData.seo.ogTitle ||
|
||||||
|
previewData.seo.seoTitle ||
|
||||||
|
previewData.seo.ogDescription ||
|
||||||
|
previewData.seo.metaDescription
|
||||||
|
);
|
||||||
|
|
||||||
const imageUrl =
|
const imageUrl =
|
||||||
previewData?.seo?.ogImage || "https://placehold.co/1200x630?text=GG+Hospital";
|
previewData?.seo?.ogImage ||
|
||||||
|
"https://placehold.co/1200x630?text=GG+Hospital";
|
||||||
|
|
||||||
const ogTitle =
|
const ogTitle =
|
||||||
previewData?.seo?.ogTitle || previewData?.seo?.seoTitle || "GG Hospital";
|
previewData?.seo?.ogTitle || previewData?.seo?.seoTitle || "GG Hospital";
|
||||||
|
|
||||||
const ogDescription =
|
const ogDescription =
|
||||||
previewData?.seo?.ogDescription || previewData?.seo?.metaDescription ||
|
previewData?.seo?.ogDescription ||
|
||||||
|
previewData?.seo?.metaDescription ||
|
||||||
"No description available";
|
"No description available";
|
||||||
|
|
||||||
const searchTitle =
|
const searchTitle =
|
||||||
previewData?.seo?.seoTitle || previewData?.seo?.ogTitle || "SEO title preview";
|
previewData?.seo?.seoTitle ||
|
||||||
|
previewData?.seo?.ogTitle ||
|
||||||
|
"SEO title preview";
|
||||||
|
|
||||||
const searchDescription =
|
const searchDescription =
|
||||||
previewData?.seo?.metaDescription || previewData?.seo?.ogDescription ||
|
previewData?.seo?.metaDescription ||
|
||||||
|
previewData?.seo?.ogDescription ||
|
||||||
"No meta description available";
|
"No meta description available";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -50,8 +76,9 @@ export default function SeoPreview({
|
|||||||
<DialogTitle className="text-xl">{title}</DialogTitle>
|
<DialogTitle className="text-xl">{title}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
{previewData ? (
|
{hasSeoData ? (
|
||||||
<div className="space-y-10 py-2">
|
<div className="space-y-10 py-2">
|
||||||
|
{/* Social Preview */}
|
||||||
<div>
|
<div>
|
||||||
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
||||||
Social Media Preview (WhatsApp / Facebook)
|
Social Media Preview (WhatsApp / Facebook)
|
||||||
@@ -87,6 +114,7 @@ export default function SeoPreview({
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Google Preview */}
|
||||||
<div>
|
<div>
|
||||||
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
||||||
Google Search Preview
|
Google Search Preview
|
||||||
@@ -115,12 +143,12 @@ export default function SeoPreview({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="p-6 text-sm text-muted-foreground">
|
<div className="flex items-center justify-center py-16 text-sm text-muted-foreground">
|
||||||
No preview data available.
|
No preview data available.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DialogFooter className="p-6 border-t bg-background z-10 mt-0">
|
<DialogFooter className="mt-0 border-t bg-background p-6">
|
||||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import {
|
|||||||
createHealthPackageApi,
|
createHealthPackageApi,
|
||||||
createCategoryApi,
|
createCategoryApi,
|
||||||
updateCategoryApi,
|
updateCategoryApi,
|
||||||
deleteCategoryApi,
|
|
||||||
HealthPackage,
|
HealthPackage,
|
||||||
HealthCategory,
|
HealthCategory,
|
||||||
} from "@/api/healthCheck";
|
} from "@/api/healthCheck";
|
||||||
|
|
||||||
import PackageInquiriesTab from "@/components/PackageInquiriesTab/PackageInquiriesTab";
|
import PackageInquiriesTab from "@/components/PackageInquiriesTab/PackageInquiriesTab";
|
||||||
import HealthPackageModal from "@/components/HealthPackageModal/HealthPackageModal";
|
import HealthPackageModal from "@/components/HealthPackageModal/HealthPackageModal";
|
||||||
|
import SeoPreview from "@/components/SeoPreview/SeoPreview";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@@ -771,86 +771,12 @@ export default function HealthPackagePage() {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
{/* --- VIEW MODAL --- */}
|
<SeoPreview
|
||||||
<Dialog open={viewModal} onOpenChange={setViewModal}>
|
open={viewModal}
|
||||||
<DialogContent className="w-full !max-w-5xl h-[90vh] flex flex-col p-0 overflow-hidden">
|
onOpenChange={setViewModal}
|
||||||
<DialogHeader className="p-6 border-b bg-background z-10">
|
previewData={selectedPackage}
|
||||||
<DialogTitle className="text-2xl">
|
url="asdfasdfasD"
|
||||||
{selectedPackage?.name}
|
/>
|
||||||
</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="flex-1 overflow-y-auto p-6 space-y-6">
|
|
||||||
<div className="flex justify-between items-center bg-muted/20 p-4 rounded-lg">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-muted-foreground uppercase font-bold">
|
|
||||||
Category
|
|
||||||
</p>
|
|
||||||
<p className="text-base font-medium">
|
|
||||||
{selectedPackage?.category?.name}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-right">
|
|
||||||
<p className="text-sm text-muted-foreground uppercase font-bold">
|
|
||||||
Pricing
|
|
||||||
</p>
|
|
||||||
<p className="text-xl font-bold">
|
|
||||||
{selectedPackage?.discountedPrice != null
|
|
||||||
? `₹${selectedPackage.discountedPrice}`
|
|
||||||
: selectedPackage?.price != null
|
|
||||||
? `₹${selectedPackage.price}`
|
|
||||||
: "Not Entered"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="font-bold text-base border-b pb-2 mb-4">
|
|
||||||
Inclusions
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-6">
|
|
||||||
{selectedPackage?.inclusions &&
|
|
||||||
typeof selectedPackage.inclusions === "object" &&
|
|
||||||
!Array.isArray(selectedPackage.inclusions) ? (
|
|
||||||
Object.entries(selectedPackage.inclusions).map(
|
|
||||||
([category, tests], idx) => (
|
|
||||||
<div key={idx}>
|
|
||||||
<h4 className="font-semibold text-sm text-primary mb-3 uppercase tracking-wider">
|
|
||||||
{category}
|
|
||||||
</h4>
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
|
||||||
{Array.isArray(tests) &&
|
|
||||||
tests.map((item, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="text-sm border p-3 rounded bg-background shadow-sm"
|
|
||||||
>
|
|
||||||
✓ {item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
|
||||||
{Array.isArray(selectedPackage?.inclusions) &&
|
|
||||||
selectedPackage.inclusions.map((item, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="text-sm border p-3 rounded bg-background shadow-sm"
|
|
||||||
>
|
|
||||||
✓ {item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<DialogFooter className="p-6 border-t">
|
|
||||||
<Button onClick={() => setViewModal(false)}>Close</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user