fancytextstuff/components/ui/FontCard.jsx

164 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 { transformText, fontTransforms } from "../fontTransforms";
import { getFontData } from "@/lib/fonts";
import fontMap from "@/lib/tailwind-font-map";
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 fontKey = fontName.toLowerCase().replace(/\s+/g, "");
const fontVarName = fontMap[fontKey];
const fontVar = fontVarName ? { fontFamily: `var(${fontVarName})` } : {};
const fontClass = fontData?.className || "";
const rawText = "Hallo Instagram!";
const transformed = transformText(rawText, fontName);
const finalText = transformed?.transformed || rawText;
const copyText = transformed?.transformed || rawText;
const handleCopy = () => {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard
.writeText(copyText)
.then(() => flashCopied())
.catch(() => fallbackCopy());
} else {
fallbackCopy();
}
};
const flashCopied = () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const fallbackCopy = () => {
const textarea = document.createElement("textarea");
textarea.value = copyText;
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: copyText,
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={finalText}
readOnly
className={`${fontClass} 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={{ ...fontVar, 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>
);
}