feat: initial commit - Moraworld Imports project
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
:root {
|
||||
--primary: #0057ff;
|
||||
--primary-dark: #003fc7;
|
||||
--accent: #ff6b00;
|
||||
--dark: #0d1117;
|
||||
--gray-900: #111827;
|
||||
--gray-500: #6b7280;
|
||||
--gray-200: #e5e7eb;
|
||||
--gray-100: #f3f4f6;
|
||||
--white: #ffffff;
|
||||
--green: #10b981;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-inter), system-ui, sans-serif;
|
||||
color: var(--gray-900);
|
||||
background: var(--white);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-inter",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Moraworld Imports — Casillero en EE.UU. para Ecuador",
|
||||
description:
|
||||
"Compra en Amazon, eBay y más. Tu casillero en New Jersey con envío y gestión aduanera a Ecuador.",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="es">
|
||||
<body className={inter.variable}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
async function getApiHealth() {
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3001";
|
||||
try {
|
||||
const res = await fetch(`${apiUrl}/api/health`, {
|
||||
next: { revalidate: 10 },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
return res.json();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function HomePage() {
|
||||
const health = await getApiHealth();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<header
|
||||
style={{
|
||||
borderBottom: "1px solid var(--gray-200)",
|
||||
padding: "16px 24px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<span style={{ fontWeight: 800, fontSize: "1.2rem", color: "var(--primary)" }}>
|
||||
Moraworld<span style={{ color: "var(--accent)" }}>.</span>Imports
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
fontSize: ".75rem",
|
||||
fontWeight: 600,
|
||||
padding: "4px 10px",
|
||||
borderRadius: 999,
|
||||
background: health?.status === "ok" ? "#D1FAE5" : "#FEF3C7",
|
||||
color: health?.status === "ok" ? "#065F46" : "#92400E",
|
||||
}}
|
||||
>
|
||||
API: {health?.status === "ok" ? "conectada" : "local / pendiente"}
|
||||
</span>
|
||||
</header>
|
||||
|
||||
<section
|
||||
style={{
|
||||
background: "linear-gradient(135deg, #0D1117 0%, #0D2150 100%)",
|
||||
padding: "80px 24px",
|
||||
color: "#fff",
|
||||
}}
|
||||
>
|
||||
<div style={{ maxWidth: 1100, margin: "0 auto" }}>
|
||||
<p
|
||||
style={{
|
||||
display: "inline-block",
|
||||
background: "rgba(0,87,255,.15)",
|
||||
border: "1px solid rgba(0,87,255,.3)",
|
||||
color: "#7AADFF",
|
||||
fontSize: ".8rem",
|
||||
fontWeight: 600,
|
||||
padding: "6px 14px",
|
||||
borderRadius: 999,
|
||||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
Fase 0 — Fundación del software
|
||||
</p>
|
||||
<h1 style={{ fontSize: "clamp(2rem, 5vw, 3rem)", fontWeight: 800, lineHeight: 1.15, marginBottom: 16 }}>
|
||||
Tu casillero en <em style={{ color: "var(--accent)", fontStyle: "normal" }}>New Jersey</em>
|
||||
<br />
|
||||
para recibir en Ecuador
|
||||
</h1>
|
||||
<p style={{ color: "#9CA3AF", maxWidth: 520, marginBottom: 32 }}>
|
||||
Monorepo activo: Next.js + NestJS + PostgreSQL. Desarrollo local con Docker; despliegue en Coolify.
|
||||
</p>
|
||||
<div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
|
||||
<a
|
||||
href="/status"
|
||||
style={{
|
||||
background: "var(--primary)",
|
||||
color: "#fff",
|
||||
padding: "14px 28px",
|
||||
borderRadius: 8,
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
Ver estado del sistema →
|
||||
</a>
|
||||
<span
|
||||
style={{
|
||||
border: "2px solid rgba(255,255,255,.2)",
|
||||
color: "#9CA3AF",
|
||||
padding: "12px 26px",
|
||||
borderRadius: 8,
|
||||
fontSize: ".9rem",
|
||||
}}
|
||||
>
|
||||
Prototipos HTML en la raíz del repo
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style={{ padding: "48px 24px", maxWidth: 1100, margin: "0 auto" }}>
|
||||
<h2 style={{ fontSize: "1.25rem", fontWeight: 700, marginBottom: 16 }}>Próximos pasos (Fase 1)</h2>
|
||||
<ul style={{ color: "var(--gray-500)", paddingLeft: 20, display: "flex", flexDirection: "column", gap: 8 }}>
|
||||
<li>Registro e inicio de sesión con JWT + MFA</li>
|
||||
<li>Asignación automática de Suite (EC-XXXXX)</li>
|
||||
<li>Pre-alertas y registro de paquetes</li>
|
||||
<li>Migración del portal desde portal-cliente.html</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
async function getHealth() {
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3001";
|
||||
const res = await fetch(`${apiUrl}/api/health`, { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("API no disponible");
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export default async function StatusPage() {
|
||||
let health: Record<string, unknown> | null = null;
|
||||
let error: string | null = null;
|
||||
|
||||
try {
|
||||
health = await getHealth();
|
||||
} catch (e) {
|
||||
error = e instanceof Error ? e.message : "Error desconocido";
|
||||
}
|
||||
|
||||
return (
|
||||
<main style={{ padding: 48, maxWidth: 720, margin: "0 auto", fontFamily: "var(--font-inter), sans-serif" }}>
|
||||
<a href="/" style={{ color: "var(--primary)", fontWeight: 600, fontSize: ".9rem" }}>
|
||||
← Volver
|
||||
</a>
|
||||
<h1 style={{ fontSize: "1.75rem", fontWeight: 800, margin: "24px 0 16px" }}>Estado del sistema</h1>
|
||||
|
||||
{error ? (
|
||||
<pre
|
||||
style={{
|
||||
background: "#FEE2E2",
|
||||
color: "#991B1B",
|
||||
padding: 20,
|
||||
borderRadius: 12,
|
||||
overflow: "auto",
|
||||
}}
|
||||
>
|
||||
{error}
|
||||
{"\n\n"}
|
||||
Asegúrate de tener corriendo:{"\n"}
|
||||
1. pnpm docker:up{"\n"}
|
||||
2. pnpm dev (api + web)
|
||||
</pre>
|
||||
) : (
|
||||
<pre
|
||||
style={{
|
||||
background: "var(--gray-100)",
|
||||
padding: 20,
|
||||
borderRadius: 12,
|
||||
overflow: "auto",
|
||||
fontSize: ".85rem",
|
||||
}}
|
||||
>
|
||||
{JSON.stringify(health, null, 2)}
|
||||
</pre>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user