feat: initial commit - Moraworld Imports project

This commit is contained in:
Lizandro Guarnizo
2026-06-01 08:06:40 -05:00
commit 094ea9cf81
47 changed files with 12844 additions and 0 deletions
+34
View File
@@ -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;
}
+26
View File
@@ -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>
);
}
+115
View File
@@ -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>
);
}
+56
View File
@@ -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>
);
}