fancytextstuff/Home.jsx

234 lines
8.2 KiB
JavaScript

import React, { useState, useEffect, useMemo, useCallback } from "react";
import { motion } from "framer-motion";
import SEOHead from "./components/SEOHead";
import MobileOptimizedHeader from "./components/MobileOptimizedHeader";
import EnhancedTextInput from "./components/EnhancedTextInput";
import ImprovedCategoryFilter from "./components/ImprovedCategoryFilter";
import PerformanceOptimizedFontCard from "./components/PerformanceOptimizedFontCard";
import InfoSection from "./components/InfoSection";
import SocialButtons from "./components/SocialButtons";
import {
fontTransforms,
getFontsByCategory,
transformText,
getPopularFonts,
} from "./components/FontTransforms";
// kleine Helper
const sArr = (v) => (Array.isArray(v) ? v : []);
const sStr = (v) => (v ?? "").toString();
const sObj = (v) => (v ?? {});
export default function Home() {
const [inputText, setInputText] = useState("Hello Instagram!");
const [selectedCategory, setSelectedCategory] = useState("all");
const [isMobile, setIsMobile] = useState(false);
const [animationsEnabled, setAnimationsEnabled] = useState(() => {
if (typeof window !== "undefined") {
const hasReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const cores = typeof navigator !== "undefined" ? navigator.hardwareConcurrency : 8;
const isLowEndDevice = (cores ?? 8) < 4;
return !hasReducedMotion && !isLowEndDevice;
}
return true;
});
// Mobile Detection
useEffect(() => {
const checkMobile = () => {
if (typeof window !== "undefined") {
setIsMobile(
window.innerWidth < 768 ||
/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
);
}
};
checkMobile();
if (typeof window !== "undefined") {
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}
}, []);
// Debounce
const [debouncedText, setDebouncedText] = useState(inputText);
useEffect(() => {
const delay = isMobile ? 200 : 100;
const t = setTimeout(() => setDebouncedText(inputText), delay);
return () => clearTimeout(t);
}, [inputText, isMobile]);
// Fonts
const availableFonts = useMemo(
() => sArr(getFontsByCategory?.(selectedCategory)),
[selectedCategory]
);
const popularFonts = useMemo(() => sArr(getPopularFonts?.()), []);
const fontCounts = useMemo(() => {
const totalFonts = Object.keys(sObj(fontTransforms)).length;
const counts = { all: totalFonts };
Object.values(sObj(fontTransforms)).forEach((font) => {
const cat = font?.category ?? "other";
counts[cat] = (counts[cat] || 0) + 1;
});
return counts;
}, []);
// Analytics
const handleFontCopy = useCallback((fontName, text) => {
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", "font_copied", {
font_name: fontName,
text_length: sStr(text).length,
category: fontTransforms?.[fontName]?.category,
});
}
}, []);
const handleQuickShare = useCallback(async () => {
if (typeof window === "undefined") return;
const shareData = {
title: "FancyText - Cool Fonts! 🔥",
text: "Check out this app for cool Instagram & TikTok fonts! 30+ fonts for free ✨",
url: window.location.href,
};
if (navigator.share) {
try {
await navigator.share(shareData);
} catch (err) {
if (err.name !== "AbortError") console.error("Share failed:", err);
}
} else {
try {
await navigator.clipboard.writeText(`${shareData.text}\n${shareData.url}`);
alert("Link copied! 📋");
} catch (err) {
console.error("Copy failed:", err);
}
}
}, []);
return (
<div className="min-h-screen bg-gradient-to-br from-pink-500 via-purple-600 to-blue-600 relative overflow-hidden">
<SEOHead currentText={inputText} />
{/* Google Fonts */}
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&family=Bebas+Neue&family=Poppins:wght@500&family=Pacifico&family=Dancing+Script&family=Anton&family=Orbitron&family=Playfair+Display&display=swap"
rel="stylesheet"
/>
{/* Background blobs */}
{animationsEnabled && !isMobile && (
<>
<div className="absolute top-20 left-10 w-72 h-72 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-30 animate-blob"></div>
<div className="absolute top-40 right-10 w-72 h-72 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-30 animate-blob animation-delay-2000"></div>
<div className="absolute -bottom-8 left-20 w-72 h-72 bg-blue-300 rounded-full mix-blend-multiply filter blur-xl opacity-30 animate-blob animation-delay-4000"></div>
</>
)}
<div className="relative z-10 container mx-auto px-2 sm:px-4 py-4 sm:py-8 max-w-6xl">
<MobileOptimizedHeader
animationsEnabled={animationsEnabled}
onToggleAnimations={setAnimationsEnabled}
totalFonts={Object.keys(sObj(fontTransforms)).length}
onQuickShare={handleQuickShare}
/>
<EnhancedTextInput
text={inputText}
onChange={setInputText}
placeholder="✍️ Enter your text:"
/>
<ImprovedCategoryFilter
selectedCategory={selectedCategory}
onCategoryChange={setSelectedCategory}
fontCounts={fontCounts}
isMobile={isMobile}
/>
{/* Font Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6 mb-8 sm:mb-12">
{availableFonts.map((fontName, index) => (
<PerformanceOptimizedFontCard
key={fontName}
fontName={fontName}
transformedText={transformText(sStr(debouncedText), fontName) ?? ""}
category={fontTransforms?.[fontName]?.category ?? "other"}
isPopular={popularFonts.includes(fontName)}
animationsEnabled={animationsEnabled}
index={index}
onCopy={handleFontCopy}
/>
))}
</div>
<SocialButtons onShare={handleQuickShare} />
<InfoSection />
<footer className="text-center text-white/60 text-xs sm:text-sm mt-8 sm:mt-12 space-y-2 px-4">
<p>
© 2024 FancyText - The best <strong>font generator for Instagram</strong> and{" "}
<strong>TikTok</strong>
</p>
<p className="text-xs">
Create cool fonts for social media posts {" "}
{Object.keys(sObj(fontTransforms)).length}+ unique fonts
</p>
<div className="flex flex-wrap justify-center gap-2 sm:gap-4 mt-4 text-xs text-white/40">
<span>SEO-optimized</span>
<span></span>
<span>Mobile-first</span>
<span></span>
<span>Performance-optimized</span>
<span></span>
<span>PWA-ready</span>
</div>
</footer>
</div>
<style jsx>{`
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.touch-manipulation {
touch-action: manipulation;
}
@keyframes blob {
0% { transform: translate(0px, 0px) scale(1); }
33% { transform: translate(30px, -50px) scale(1.1); }
66% { transform: translate(-20px, 20px) scale(0.9); }
100% { transform: translate(0px, 0px) scale(1); }
}
.animate-blob { animation: blob 7s infinite; }
.animation-delay-2000 { animation-delay: 2s; }
.animation-delay-4000 { animation-delay: 4s; }
@media (hover: hover) {
.hover-lift:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
}
}
@media (max-width: 640px) {
.text-responsive {
font-size: 1.25rem;
line-height: 1.4;
}
}
@media (display-mode: standalone) {
body { padding-top: env(safe-area-inset-top); }
}
`}</style>
</div>
);
}