155 lines
4.8 KiB
JavaScript
155 lines
4.8 KiB
JavaScript
// components/ui/FontCard.jsx
|
||
import React, { useState } from "react";
|
||
import { Card } from "@/components/ui/card";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Badge } from "@/components/ui/badge";
|
||
import { Copy, Check, Heart, Share2, Info } from "lucide-react";
|
||
import { fontTransforms } from "../fontTransforms";
|
||
import { getFontData } from "@/lib/fonts";
|
||
|
||
export default function FontCard({
|
||
fontName,
|
||
transformedText,
|
||
category,
|
||
isPopular,
|
||
index = 0,
|
||
}) {
|
||
const [copied, setCopied] = useState(false);
|
||
const [liked, setLiked] = useState(false);
|
||
|
||
const fontInfo = fontTransforms[fontName];
|
||
const fontData = getFontData(fontName);
|
||
const displayText = transformedText || "Hallo Instagram!";
|
||
|
||
const handleCopy = () => {
|
||
if (navigator.clipboard && window.isSecureContext) {
|
||
navigator.clipboard
|
||
.writeText(displayText)
|
||
.then(() => flashCopied())
|
||
.catch(() => fallbackCopy());
|
||
} else {
|
||
fallbackCopy();
|
||
}
|
||
};
|
||
|
||
const flashCopied = () => {
|
||
setCopied(true);
|
||
setTimeout(() => setCopied(false), 2000);
|
||
};
|
||
|
||
const fallbackCopy = () => {
|
||
const textarea = document.createElement("textarea");
|
||
textarea.value = displayText;
|
||
textarea.setAttribute("readonly", "");
|
||
textarea.style.position = "fixed";
|
||
textarea.style.top = "0";
|
||
textarea.style.left = "0";
|
||
textarea.style.width = "1px";
|
||
textarea.style.height = "1px";
|
||
textarea.style.padding = "0";
|
||
textarea.style.border = "none";
|
||
textarea.style.outline = "none";
|
||
textarea.style.boxShadow = "none";
|
||
textarea.style.background = "transparent";
|
||
|
||
document.body.appendChild(textarea);
|
||
textarea.focus();
|
||
textarea.select();
|
||
try {
|
||
document.execCommand("copy");
|
||
flashCopied();
|
||
} catch (err) {
|
||
console.error("Fallback Copy fehlgeschlagen:", err);
|
||
}
|
||
document.body.removeChild(textarea);
|
||
};
|
||
|
||
const handleShare = async () => {
|
||
if (!navigator.share) return;
|
||
try {
|
||
await navigator.share({
|
||
title: `FancyText – ${fontName}`,
|
||
text: displayText,
|
||
url: window.location.href,
|
||
});
|
||
} catch (err) {
|
||
console.error("Share fehlgeschlagen:", err);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div style={{ pointerEvents: "none" }}>
|
||
<Card className="bg-white/90 backdrop-blur-sm border-0 shadow-xl hover:shadow-2xl transition-all duration-300 overflow-hidden">
|
||
<div className="p-6">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<div className="flex items-center gap-2">
|
||
<h3 className="font-semibold text-gray-800 capitalize">{fontName}</h3>
|
||
{isPopular && (
|
||
<Badge className="bg-gradient-to-r from-pink-500 to-purple-500 text-white text-[10px] uppercase tracking-wide">
|
||
Beliebt
|
||
</Badge>
|
||
)}
|
||
{category && (
|
||
<Badge className="bg-gray-200 text-gray-600 text-[10px] uppercase tracking-wide">
|
||
{category}
|
||
</Badge>
|
||
)}
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
onClick={() => setLiked(!liked)}
|
||
className={liked ? "text-pink-500" : "text-gray-400"}
|
||
>
|
||
<Heart className={`w-4 h-4 ${liked ? "fill-current" : ""}`} />
|
||
</Button>
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
onClick={handleShare}
|
||
className="text-gray-400 hover:text-blue-500"
|
||
>
|
||
<Share2 className="w-4 h-4" />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{fontInfo?.description && (
|
||
<p className="text-xs text-gray-500 mb-3 flex items-center gap-1">
|
||
<Info className="w-3 h-3" />
|
||
{fontInfo.description}
|
||
</p>
|
||
)}
|
||
|
||
<input
|
||
type="text"
|
||
value={displayText}
|
||
readOnly
|
||
className={`${fontData.className} text-2xl md:text-3xl mb-6 p-4 bg-gray-50 rounded-xl text-center text-gray-800 min-h-[80px] w-full select-all border-0 focus:ring-0`}
|
||
style={{ lineHeight: "1.2" }}
|
||
/>
|
||
|
||
<Button
|
||
onClick={handleCopy}
|
||
className="w-full bg-gradient-to-r from-pink-500 to-purple-500 hover:from-pink-600 hover:to-purple-600 text-white font-medium py-3 rounded-xl shadow-lg pointer-events-auto"
|
||
disabled={copied}
|
||
>
|
||
{copied ? (
|
||
<>
|
||
<Check className="w-4 h-4 mr-2" />
|
||
Copy!
|
||
</>
|
||
) : (
|
||
<>
|
||
<Copy className="w-4 h-4 mr-2" />
|
||
Copy now
|
||
</>
|
||
)}
|
||
</Button>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|