feat: phase 3 redesign, game images, auth system, vm guides, service isolation
Some checks failed
Deploy Multi-VM / Deploy VM Web (push) Has been cancelled
Deploy Multi-VM / Deploy VM Auth (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.fusionfall.yml, VM_FUSIONFALL_HOST, VM_FUSIONFALL_SSH_KEY, VM_FUSIONFALL_USER, fusionfall) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.maple2.yml, VM_MAPLE2_HOST, VM_MAPLE2_SSH_KEY, VM_MAPLE2_USER, maple2) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.minecraft.yml, VM_MINECRAFT_HOST, VM_MINECRAFT_SSH_KEY, VM_MINECRAFT_USER, minecraft) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.retro.yml, VM_RETRO_HOST, VM_RETRO_SSH_KEY, VM_RETRO_USER, retro) (push) Has been cancelled
Some checks failed
Deploy Multi-VM / Deploy VM Web (push) Has been cancelled
Deploy Multi-VM / Deploy VM Auth (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.fusionfall.yml, VM_FUSIONFALL_HOST, VM_FUSIONFALL_SSH_KEY, VM_FUSIONFALL_USER, fusionfall) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.maple2.yml, VM_MAPLE2_HOST, VM_MAPLE2_SSH_KEY, VM_MAPLE2_USER, maple2) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.minecraft.yml, VM_MINECRAFT_HOST, VM_MINECRAFT_SSH_KEY, VM_MINECRAFT_USER, minecraft) (push) Has been cancelled
Deploy Multi-VM / Deploy Game Servers (docker-compose.retro.yml, VM_RETRO_HOST, VM_RETRO_SSH_KEY, VM_RETRO_USER, retro) (push) Has been cancelled
- Redesign all internal pages to warm/gold aesthetic (catalog, game detail, documentary, about, donate, community, guides, contact, server-status, login, profile, admin, not-found) - Add real cover images for all 4 games via Strapi CMS with getImageUrl helper - Integrate NextAuth v5 with Authentik OIDC authentication - Add new public pages: community, guides, contact, server-status - Add new protected pages: login, profile, admin dashboard - Remove legacy AFC/MercadoPago system entirely - Add Docker Compose split files for service isolation (main, auth, fusionfall, nier) - Add OpenFusion VM deployment configs (config.vm.ini, systemd service, README-VM) - Add NieR Reincarnation server guide and desktop client guide - Add architecture docs for multi-VM deployment - Add healthcheck, SSE, contact, newsletter, admin API routes - Add reusable UI components, skeleton loaders, activity feed, bookmark system - Update deployment and game server documentation
This commit is contained in:
183
apps/web/src/app/[locale]/community/page.tsx
Normal file
183
apps/web/src/app/[locale]/community/page.tsx
Normal file
@@ -0,0 +1,183 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from "next-intl";
|
||||
import { motion } from "framer-motion";
|
||||
import { useLocale } from "next-intl";
|
||||
import Link from "next/link";
|
||||
|
||||
function DiscordIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function GitHubIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function HeartIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function MessageIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const cardVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: (i: number) => ({
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { delay: i * 0.1, duration: 0.5, ease: "easeOut" as const },
|
||||
}),
|
||||
};
|
||||
|
||||
const channels = [
|
||||
{
|
||||
name: "Discord",
|
||||
description: "Join our community Discord to chat with other players, get support, and stay updated on new releases.",
|
||||
href: "https://discord.gg/projectafterlife",
|
||||
icon: DiscordIcon,
|
||||
color: "text-[#d4a574]",
|
||||
bg: "bg-[rgba(212,165,116,0.08)] border-[rgba(212,165,116,0.15)] hover:border-[rgba(212,165,116,0.35)]",
|
||||
btn: "bg-[#d4a574] hover:bg-[#e8c4a0] text-[#0a0a0f]",
|
||||
btnText: "text-[#0a0a0f]",
|
||||
label: "Join Discord",
|
||||
},
|
||||
{
|
||||
name: "GitHub",
|
||||
description: "Our code is open source. Contribute to the project, report issues, or explore our repositories.",
|
||||
href: "https://github.com/projectafterlife",
|
||||
icon: GitHubIcon,
|
||||
color: "text-[#a0a0a8]",
|
||||
bg: "bg-[rgba(255,255,255,0.03)] border-[rgba(255,255,255,0.08)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
btn: "bg-[#1a1a24] hover:bg-[#2a2a34] text-[#f5f5f7]",
|
||||
btnText: "text-[#f5f5f7]",
|
||||
label: "View GitHub",
|
||||
},
|
||||
{
|
||||
name: "Forums",
|
||||
description: "Long-form discussions, guides, bug reports, and feature requests. The heart of our community.",
|
||||
href: "#",
|
||||
icon: MessageIcon,
|
||||
color: "text-[#e8c4a0]",
|
||||
bg: "bg-[rgba(232,196,160,0.08)] border-[rgba(232,196,160,0.15)] hover:border-[rgba(232,196,160,0.35)]",
|
||||
btn: "bg-[#e8c4a0] hover:bg-[#d4a574] text-[#0a0a0f]",
|
||||
btnText: "text-[#0a0a0f]",
|
||||
label: "Coming Soon",
|
||||
},
|
||||
{
|
||||
name: "Contribute",
|
||||
description: "Help us preserve gaming history. We need developers, writers, translators, and testers.",
|
||||
href: "/donate",
|
||||
icon: HeartIcon,
|
||||
color: "text-rose-400",
|
||||
bg: "bg-rose-500/8 border-rose-500/15 hover:border-rose-500/35",
|
||||
btn: "bg-rose-600 hover:bg-rose-500 text-white",
|
||||
btnText: "text-white",
|
||||
label: "How to Help",
|
||||
},
|
||||
];
|
||||
|
||||
export default function CommunityPage() {
|
||||
const locale = useLocale();
|
||||
const isEs = locale === "es";
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4 py-12">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<h1
|
||||
className="text-[clamp(2rem,4vw,3.5rem)] font-extrabold mb-4 tracking-tight"
|
||||
style={{ fontFamily: "var(--font-display)", letterSpacing: "-0.02em" }}
|
||||
>
|
||||
{isEs ? "Comunidad" : "Community"}
|
||||
</h1>
|
||||
<p className="text-lg text-[#a0a0a8] max-w-2xl mx-auto leading-relaxed">
|
||||
{isEs
|
||||
? "Project Afterlife es impulsado por su comunidad. Únete a nosotros para preservar la historia de los juegos juntos."
|
||||
: "Project Afterlife is driven by its community. Join us in preserving gaming history together."}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{channels.map((channel, i) => {
|
||||
const Icon = channel.icon;
|
||||
const isExternal = channel.href.startsWith("http");
|
||||
const Wrapper = isExternal ? "a" : Link;
|
||||
const wrapperProps = isExternal
|
||||
? { href: channel.href, target: "_blank", rel: "noopener noreferrer" }
|
||||
: { href: channel.href };
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
key={channel.name}
|
||||
custom={i}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-50px" }}
|
||||
variants={cardVariants}
|
||||
>
|
||||
<Wrapper
|
||||
{...wrapperProps}
|
||||
className={`block rounded-2xl border p-8 transition-all duration-300 hover:scale-[1.02] ${channel.bg}`}
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className={`p-3 rounded-xl bg-black/30 ${channel.color}`}>
|
||||
<Icon className="w-6 h-6" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-semibold text-[#f5f5f7] mb-2">{channel.name}</h3>
|
||||
<p className="text-sm text-[#a0a0a8] leading-relaxed mb-4">
|
||||
{channel.description}
|
||||
</p>
|
||||
<span
|
||||
className={`inline-block px-4 py-1.5 rounded-lg text-sm font-medium transition-colors ${channel.btn}`}
|
||||
>
|
||||
{channel.label}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Wrapper>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.4, duration: 0.6 }}
|
||||
className="mt-16 rounded-2xl border border-[rgba(255,255,255,0.08)] bg-[#12121a] p-8 text-center"
|
||||
>
|
||||
<h2 className="text-2xl font-semibold mb-3">
|
||||
{isEs ? "Código de Conducta" : "Code of Conduct"}
|
||||
</h2>
|
||||
<p className="text-[#a0a0a8] max-w-2xl mx-auto leading-relaxed">
|
||||
{isEs
|
||||
? "Todos los miembros de nuestra comunidad deben tratar a los demás con respeto. No se tolera el acoso, la discriminación ni el comportamiento tóxico. Queremos que este sea un espacio seguro y acogedor para todos los amantes de los juegos."
|
||||
: "All members of our community must treat others with respect. Harassment, discrimination, and toxic behavior are not tolerated. We want this to be a safe and welcoming space for all game lovers."}
|
||||
</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user