feat: seo preview #44
@@ -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";
|
||||
|
||||
interface SeoPreviewData {
|
||||
@@ -30,17 +36,37 @@ export default function SeoPreview({
|
||||
title = "SEO Preview",
|
||||
}: SeoPreviewProps) {
|
||||
const previewUrl = url || "#";
|
||||
|
||||
const hasSeoData =
|
||||
!!previewData?.seo &&
|
||||
!!(
|
||||
previewData.seo.ogImage ||
|
||||
previewData.seo.ogTitle ||
|
||||
previewData.seo.seoTitle ||
|
||||
previewData.seo.ogDescription ||
|
||||
previewData.seo.metaDescription
|
||||
);
|
||||
|
||||
const imageUrl =
|
||||
previewData?.seo?.ogImage || "https://placehold.co/1200x630?text=GG+Hospital";
|
||||
previewData?.seo?.ogImage ||
|
||||
"https://placehold.co/1200x630?text=GG+Hospital";
|
||||
|
||||
const ogTitle =
|
||||
previewData?.seo?.ogTitle || previewData?.seo?.seoTitle || "GG Hospital";
|
||||
|
||||
const ogDescription =
|
||||
previewData?.seo?.ogDescription || previewData?.seo?.metaDescription ||
|
||||
previewData?.seo?.ogDescription ||
|
||||
previewData?.seo?.metaDescription ||
|
||||
"No description available";
|
||||
|
||||
const searchTitle =
|
||||
previewData?.seo?.seoTitle || previewData?.seo?.ogTitle || "SEO title preview";
|
||||
previewData?.seo?.seoTitle ||
|
||||
previewData?.seo?.ogTitle ||
|
||||
"SEO title preview";
|
||||
|
||||
const searchDescription =
|
||||
previewData?.seo?.metaDescription || previewData?.seo?.ogDescription ||
|
||||
previewData?.seo?.metaDescription ||
|
||||
previewData?.seo?.ogDescription ||
|
||||
"No meta description available";
|
||||
|
||||
return (
|
||||
@@ -50,8 +76,9 @@ export default function SeoPreview({
|
||||
<DialogTitle className="text-xl">{title}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
{previewData ? (
|
||||
{hasSeoData ? (
|
||||
<div className="space-y-10 py-2">
|
||||
{/* Social Preview */}
|
||||
<div>
|
||||
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
||||
Social Media Preview (WhatsApp / Facebook)
|
||||
@@ -87,6 +114,7 @@ export default function SeoPreview({
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Google Preview */}
|
||||
<div>
|
||||
<p className="mb-4 text-sm font-semibold text-muted-foreground">
|
||||
Google Search Preview
|
||||
@@ -115,12 +143,12 @@ export default function SeoPreview({
|
||||
</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.
|
||||
</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)}>
|
||||
Close
|
||||
</Button>
|
||||
|
||||
@@ -9,13 +9,13 @@ import {
|
||||
createHealthPackageApi,
|
||||
createCategoryApi,
|
||||
updateCategoryApi,
|
||||
deleteCategoryApi,
|
||||
HealthPackage,
|
||||
HealthCategory,
|
||||
} from "@/api/healthCheck";
|
||||
|
||||
import PackageInquiriesTab from "@/components/PackageInquiriesTab/PackageInquiriesTab";
|
||||
import HealthPackageModal from "@/components/HealthPackageModal/HealthPackageModal";
|
||||
import SeoPreview from "@/components/SeoPreview/SeoPreview";
|
||||
|
||||
import {
|
||||
Table,
|
||||
@@ -771,86 +771,12 @@ export default function HealthPackagePage() {
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* --- VIEW MODAL --- */}
|
||||
<Dialog open={viewModal} onOpenChange={setViewModal}>
|
||||
<DialogContent className="w-full !max-w-5xl h-[90vh] flex flex-col p-0 overflow-hidden">
|
||||
<DialogHeader className="p-6 border-b bg-background z-10">
|
||||
<DialogTitle className="text-2xl">
|
||||
{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>
|
||||
<SeoPreview
|
||||
open={viewModal}
|
||||
onOpenChange={setViewModal}
|
||||
previewData={selectedPackage}
|
||||
url="asdfasdfasD"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user