Seed: music template (13 files)
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
import { toast } from "sonner";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Music, Send, Youtube, Twitter, Instagram } from "lucide-react";
|
||||||
|
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
const { mutate: subscribe } = useSaasMutation("email", "/send/newsletter-confirm");
|
||||||
|
|
||||||
|
const handleSubscribe = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.currentTarget as HTMLFormElement;
|
||||||
|
const email = (new FormData(form).get("email") as string) || "";
|
||||||
|
try {
|
||||||
|
await subscribe({ email });
|
||||||
|
toast.success("You are on the list!");
|
||||||
|
form.reset();
|
||||||
|
} catch {
|
||||||
|
toast.error("Could not subscribe. Please try again.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamLinks = [
|
||||||
|
{ name: "Spotify", href: "#" },
|
||||||
|
{ name: "Apple Music", href: "#" },
|
||||||
|
{ name: "YouTube Music", href: "#" },
|
||||||
|
{ name: "SoundCloud", href: "#" },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer className="bg-slate-950 text-slate-300 py-24 border-t border-purple-900/20">
|
||||||
|
<div className="mx-auto max-w-7xl px-6">
|
||||||
|
<div className="grid md:grid-cols-4 gap-12">
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center gap-2 text-xl font-black text-white mb-3">
|
||||||
|
<Music className="h-5 w-5 text-purple-400" />
|
||||||
|
Nova Eclipse
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-slate-400 mb-4">Music that transcends boundaries.</p>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{[Instagram, Twitter, Youtube].map((Icon, i) => (
|
||||||
|
<a key={i} href="#" className="text-slate-400 hover:text-purple-400 transition-colors"><Icon className="h-5 w-5" /></a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-semibold text-white uppercase tracking-wider mb-4">Quick Links</div>
|
||||||
|
<nav className="flex flex-col gap-2 text-sm">
|
||||||
|
{[{ label: "Music", to: "/music" }, { label: "Tour", to: "/tour" }, { label: "About", to: "/about" }].map((l) => (
|
||||||
|
<Link key={l.to} to={l.to} className="text-slate-400 hover:text-purple-400 transition-colors">{l.label}</Link>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-semibold text-white uppercase tracking-wider mb-4">Stream</div>
|
||||||
|
<nav className="flex flex-col gap-2 text-sm">
|
||||||
|
{streamLinks.map((l) => (
|
||||||
|
<a key={l.name} href={l.href} className="text-slate-400 hover:text-purple-400 transition-colors">{l.name}</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-semibold text-white uppercase tracking-wider mb-4">Newsletter</div>
|
||||||
|
<p className="text-sm text-slate-400 mb-3">Join the fan club for exclusive drops, pre-sale codes, and behind-the-scenes content.</p>
|
||||||
|
<form onSubmit={handleSubscribe} className="flex gap-2">
|
||||||
|
<Input type="email" name="email" required placeholder="you@email.com" className="bg-slate-900 border-slate-700 text-white placeholder:text-slate-500 flex-1" />
|
||||||
|
<Button type="submit" size="icon" className="bg-purple-600 hover:bg-purple-500 active:scale-[0.98] text-white shrink-0"><Send className="h-4 w-4" /></Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-12 pt-8 border-t border-purple-900/20 text-center">
|
||||||
|
<div className="text-sm text-slate-500">© 2026 Nova Eclipse. All rights reserved.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user