diff --git a/index.js b/index.js index b7515df..e51cbf0 100644 --- a/index.js +++ b/index.js @@ -1,44 +1,24 @@ import express from "express"; -import fs from "fs"; const app = express(); // Static file serving middleware app.use(express.static("public")); -// Custom static file serving -// app.get("/{:file}", (req, res, next) => { -// const fileName = req.params.file ?? "index.html"; +app.set("view engine", "ejs"); -// // Verificar si archivo existe -// if (!fs.existsSync(fileName)) { -// next(); -// return; -// } - -// const extension = fileName.split(".")[1]; - -// if (extension === "html") { -// res.setHeader("Content-Type", "text/html"); -// } else if (extension === "css") { -// res.setHeader("Content-Type", "text/css"); -// } else if (extension === "json") { -// res.setHeader("Content-Type", "application/json"); -// } else if (extension === "jpg") { -// res.setHeader("Content-Type", "image/jpg"); -// } else if (extension === "png") { -// res.setHeader("Content-Type", "image/png"); -// } - -// return res.sendFile(fileName, { root: "." }); -// }); +// Routes +app.get("/", (req, res) => { + res.render("index.ejs", { + nombre: "Codeable", + tecnologias: ["HTML", "CSS", "JS"], + }); +}); app.use((req, res, next) => { res.status(404).sendFile("404.html", { root: "public" }); }); -const PORT = process.env.PORT || 3000; - -app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`); +app.listen(3000, () => { + console.log(`Server is running on http://localhost:3000`); }); diff --git a/package-lock.json b/package-lock.json index ff04da4..e360bb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "ejs": "^3.1.10", "express": "^5.1.0" } }, @@ -25,6 +26,18 @@ "node": ">= 0.6" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", @@ -45,6 +58,15 @@ "node": ">=18" } }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -168,6 +190,21 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -264,6 +301,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, "node_modules/finalhandler": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", @@ -439,6 +485,23 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -490,6 +553,18 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -557,6 +632,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", diff --git a/package.json b/package.json index 21cf130..7be5df2 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "license": "ISC", "type": "module", "dependencies": { + "ejs": "^3.1.10", "express": "^5.1.0" } } diff --git a/public/404.html b/public/404.html index 6a3fff9..ab62d6c 100644 --- a/public/404.html +++ b/public/404.html @@ -1,12 +1,32 @@ - + - Archivo no encontrado + Full Stock | Página no encontrada + + + + + + -

404 - Archivo no encontrado

-

Lo sentimos, el archivo que buscas no existe.

+
+
+
+

Página No Encontrada

+

+ La página que estás buscando no existe o ha sido movida +

+ Volver al Inicio +
+
+
diff --git a/public/about.html b/public/about.html deleted file mode 100644 index cacc286..0000000 --- a/public/about.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Acerca de Nosotros - - - -

Acerca de Nosotros

- - diff --git a/public/cart.html b/public/cart.html new file mode 100644 index 0000000..130ecbe --- /dev/null +++ b/public/cart.html @@ -0,0 +1,259 @@ + + + + + + Full Stock | Inicio + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+

Carrito de compras

+
+
+
+ Polo React +
+
+
+

Polo React

+
+ +
+
+ +
+
+
+
+ Taza GitHub +
+
+
+

Taza GitHub

+
+ +
+
+ +
+
+
+

Total

+

S/ 54.99

+
+ +
+
+
+
+ +
+ + diff --git a/public/category.html b/public/category.html new file mode 100644 index 0000000..cc72d10 --- /dev/null +++ b/public/category.html @@ -0,0 +1,371 @@ + + + + + + Full Stock | Polos + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+
+

Polos

+

+ Polos exclusivos con diseños que todo desarrollador querrá + lucir. Ideales para llevar el código a donde vayas. +

+
+
+
+
+ +
+
+ +
+ + diff --git a/public/checkout.html b/public/checkout.html new file mode 100644 index 0000000..adfbbc2 --- /dev/null +++ b/public/checkout.html @@ -0,0 +1,260 @@ + + + + + + Full Stock | Inicio + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+
+
+

+ Resumen de la orden +

+
+
+
+ Polo React +
+
+

+ Polo React +

+
+

2

+ +

S/ 20

+
+
+
+
+
+ Taza GitHub +
+
+

+ Taza GitHub +

+
+

1

+ +

S/ 14.99

+
+
+
+
+

Total

+

S/ 54.99

+
+
+
+
+ + Información de contacto + +
+ + +
+ +
+
+ + Información de envío + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+ +
+ + diff --git a/public/css/1_foundation/colors.css b/public/css/1_foundation/colors.css new file mode 100644 index 0000000..8aacf29 --- /dev/null +++ b/public/css/1_foundation/colors.css @@ -0,0 +1,136 @@ +@layer definitions { + :root { + /* Colores base */ + --white: hsl(0 0% 100%); + --black: hsl(0 0% 0%); + --base-background: var(--white); + + --accent-1: hsl(240 33% 99%); + --accent-2: hsl(240 33% 98%); + --accent-3: hsl(240 33% 97%); + --accent-4: hsl(240 33% 94%); + --accent-5: hsl(240 33% 90%); + --accent-6: hsl(240 33% 83%); + --accent-7: hsl(240 73% 80%); + --accent-8: hsl(240 73% 74%); + --accent-9: hsl(240 62% 57%); + --accent-10: hsl(240 61% 52%); + --accent-11: hsl(240 54% 51%); + --accent-12: hsl(240 55% 22%); + --accent-a1: hsl(240 100% 50% / 0.01); + --accent-a2: hsl(240 100% 50% / 0.03); + --accent-a3: hsl(240 90% 47% / 0.06); + --accent-a4: hsl(240 100% 50% / 0.1); + --accent-a5: hsl(240 100% 50% / 0.15); + --accent-a6: hsl(240 100% 50% / 0.2); + --accent-a7: hsl(240 90% 45% / 0.28); + --accent-a8: hsl(240 85% 43% / 0.39); + --accent-a9: hsl(240 75% 38% / 0.64); + --accent-a10: hsl(240 72% 35% / 0.68); + --accent-a11: hsl(240 67% 34% / 0.67); + --accent-a12: hsl(240 85% 14% / 0.85); + --accent-contrast: var(--white); + + --neutral-1: hsl(240 9% 99%); + --neutral-2: hsl(240 8% 98%); + --neutral-3: hsl(240 7% 95%); + --neutral-4: hsl(240 7% 92%); + --neutral-5: hsl(240 6% 89%); + --neutral-6: hsl(240 6% 86%); + --neutral-7: hsl(240 8% 83%); + --neutral-8: hsl(240 11% 76%); + --neutral-9: hsl(240 9% 59%); + --neutral-10: hsl(240 8% 53%); + --neutral-11: hsl(240 7% 41%); + --neutral-12: hsl(240 10% 14%); + --neutral-a1: hsl(240 100% 33% / 0.01); + --neutral-a2: hsl(240 100% 33% / 0.02); + --neutral-a3: hsl(240 100% 20% / 0.06); + --neutral-a4: hsl(240 100% 18% / 0.09); + --neutral-a5: hsl(240 100% 20% / 0.12); + --neutral-a6: hsl(240 100% 18% / 0.15); + --neutral-a7: hsl(240 100% 18% / 0.2); + --neutral-a8: hsl(240 100% 19% / 0.27); + --neutral-a9: hsl(240 100% 13% / 0.45); + --neutral-a10: hsl(240 100% 11% / 0.5); + --neutral-a11: hsl(240 100% 8% / 0.62); + --neutral-a12: hsl(240 100% 4% / 0.89); + --neutral-contrast: var(--white); + + /* Tokens de color */ + --background: var(--base-background); + --foreground: var(--neutral-12); + --accent-background: var(--accent-3); + --accent-foreground: var(--accent-11); + --muted-background: var(--neutral-a2); + --muted-foreground: var(--neutral-11); + --primary-background: var(--accent-9); + --primary-foreground: var(--accent-contrast); + --secondary-background: var(--neutral-3); + --secondary-foreground: var(--neutral-11); + --border: var(--neutral-7); + --outline: var(--accent-11); + --separator: var(--neutral-6); + --primary-background-hover: var(--accent-10); + --secondary-background-hover: var(--neutral-4); + --border-hover: var(--neutral-8); + } + + @media (prefers-color-scheme: dark) { + :root { + --base-background: var(--neutral-1); + + --accent-1: hsl(240 22% 10%); + --accent-2: hsl(244 25% 12%); + --accent-3: hsl(237 38% 20%); + --accent-4: hsl(236 45% 27%); + --accent-5: hsl(237 41% 32%); + --accent-6: hsl(239 36% 37%); + --accent-7: hsl(240 34% 44%); + --accent-8: hsl(241 36% 52%); + --accent-9: hsl(240 60% 60%); + --accent-10: hsl(242 64% 64%); + --accent-11: hsl(246 100% 83%); + --accent-12: hsl(242 94% 94%); + --accent-a1: hsl(240 99% 60% / 0.05); + --accent-a2: hsl(244 94% 64% / 0.09); + --accent-a3: hsl(237 100% 66% / 0.23); + --accent-a4: hsl(236 100% 65% / 0.35); + --accent-a5: hsl(237 98% 67% / 0.42); + --accent-a6: hsl(239 97% 71% / 0.48); + --accent-a7: hsl(240 99% 73% / 0.56); + --accent-a8: hsl(240 99% 74% / 0.67); + --accent-a9: hsl(240 99% 71% / 0.83); + --accent-a10: hsl(242 100% 74% / 0.86); + --accent-a11: hsl(246 100% 83%); + --accent-a12: hsl(242 100% 94%); + --accent-contrast: var(--white); + + --neutral-1: hsl(240 6% 7%); + --neutral-2: hsl(220 6% 10%); + --neutral-3: hsl(225 6% 14%); + --neutral-4: hsl(210 7% 16%); + --neutral-5: hsl(214 7% 19%); + --neutral-6: hsl(213 8% 23%); + --neutral-7: hsl(213 8% 28%); + --neutral-8: hsl(212 8% 38%); + --neutral-9: hsl(219 6% 44%); + --neutral-10: hsl(222 5% 49%); + --neutral-11: hsl(216 7% 71%); + --neutral-12: hsl(220 9% 94%); + --neutral-a1: hsl(0 0% 0%); + --neutral-a2: hsl(184 63% 91% / 0.04); + --neutral-a3: hsl(211 66% 92% / 0.08); + --neutral-a4: hsl(198 73% 90% / 0.11); + --neutral-a5: hsl(208 95% 92% / 0.15); + --neutral-a6: hsl(208 91% 92% / 0.19); + --neutral-a7: hsl(208 100% 93% / 0.25); + --neutral-a8: hsl(208 100% 93% / 0.36); + --neutral-a9: hsl(216 88% 93% / 0.43); + --neutral-a10: hsl(220 86% 95% / 0.48); + --neutral-a11: hsl(212 87% 97% / 0.71); + --neutral-a12: hsl(220 100% 99% / 0.94); + --neutral-contrast: var(--white); + } + } +} diff --git a/public/css/1_foundation/global.css b/public/css/1_foundation/global.css new file mode 100644 index 0000000..7a3aa25 --- /dev/null +++ b/public/css/1_foundation/global.css @@ -0,0 +1,74 @@ +@layer global { + :root { + color-scheme: light dark; + } + + body { + font-family: var(--family-text); + font-size: 1rem; + line-height: 1.5rem; + + color: var(--foreground); + background-color: var(--background); + } + + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: var(--family-heading); + } + + code { + font-family: var(--family-monospace); + } + + em { + font-family: var(--family-emphasis); + } + + hr { + border: none; + border-top: 1px solid var(--separator); + } + + label { + font-size: 0.875rem; + font-weight: 500; + line-height: 1em; + } + + input, + select { + height: 2.5rem; + width: 100%; + padding: 0.5rem 0.75rem; + border-radius: 0.75rem; + border: 1px solid var(--border); + + font-size: 0.875rem; + line-height: 1.5rem; + background-color: var(--background); + } + + fieldset { + all: unset; + } + + :focus-visible { + outline: 2px solid var(--outline); + outline-offset: 2px; + } + + /*Account for sticky header height (3rem) + gap (2.5rem) */ + :focus { + scroll-margin-top: calc(3rem + 2.5rem); + } + + * { + border-color: var(--border); + border-style: none; + } +} diff --git a/public/css/1_foundation/reset.css b/public/css/1_foundation/reset.css new file mode 100644 index 0000000..38c8628 --- /dev/null +++ b/public/css/1_foundation/reset.css @@ -0,0 +1,81 @@ +@layer reset { + /* 1. Use a more-intuitive box-sizing model */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* 2. Remove default margin */ + * { + margin: 0; + } + + body { + /* 3. Add accessible line-height */ + line-height: 1.5; + /* 4. Improve text rendering */ + -webkit-font-smoothing: antialiased; + } + + /* 5. Improve media defaults */ + img, + picture, + video, + canvas, + svg { + display: block; + max-width: 100%; + } + + /* 6. Inherit fonts for form controls */ + input, + button, + textarea, + select { + font: inherit; + } + + /* 7. Avoid text overflows */ + p, + h1, + h2, + h3, + h4, + h5, + h6 { + overflow-wrap: break-word; + } + + /* 8. Improve line wrapping */ + p { + text-wrap: pretty; + } + h1, + h2, + h3, + h4, + h5, + h6 { + text-wrap: balance; + } + + /* Codeable extra resets */ + + /* Set default body height */ + body { + min-height: 100vh; + } + + /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ + ul[role="list"], + ol[role="list"] { + list-style: none; + } +} + +a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; +} diff --git a/public/css/1_foundation/typography.css b/public/css/1_foundation/typography.css new file mode 100644 index 0000000..3c3f4e8 --- /dev/null +++ b/public/css/1_foundation/typography.css @@ -0,0 +1,14 @@ +@layer definitions { + :root { + /* Font stacks */ + --family-text: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", + Roboto, "Helvetica Neue", Arial, sans-serif; + --family-heading: var(--family-text); + --family-display: "Protest Guerrilla", "Protest Strike", "Stencil", "Impact", + sans-serif; + --family-code: "Source Code Pro", "Menlo", "Consolas", "Monaco", + "Courier New", monospace; + --family-emphasis: "Lora", "Georgia", "Palatino Linotype", "Book Antiqua", + "Times New Roman", serif; + } +} diff --git a/public/css/2_layouts/container.css b/public/css/2_layouts/container.css new file mode 100644 index 0000000..5dce272 --- /dev/null +++ b/public/css/2_layouts/container.css @@ -0,0 +1,27 @@ +@layer layouts { + .container { + margin-left: auto; + margin-right: auto; + max-width: 80rem; + padding-left: 1rem; + padding-right: 1rem; + } + + .container--sm { + max-width: 48rem; + } + + @media (min-width: 40rem) { + .container { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + } + + @media (min-width: 64rem) { + .container { + padding-left: 2rem; + padding-right: 2rem; + } + } +} diff --git a/public/css/2_layouts/section.css b/public/css/2_layouts/section.css new file mode 100644 index 0000000..6d7b16c --- /dev/null +++ b/public/css/2_layouts/section.css @@ -0,0 +1,20 @@ +@layer layouts { + .section { + padding-top: 3rem; + padding-bottom: 3rem; + } + + @media (min-width: 40rem) { + .section { + padding-top: 4rem; + padding-bottom: 4rem; + } + } + + @media (min-width: 64rem) { + .section { + padding-top: 6rem; + padding-bottom: 6rem; + } + } +} diff --git a/public/css/3_components/button.css b/public/css/3_components/button.css new file mode 100644 index 0000000..ffc4add --- /dev/null +++ b/public/css/3_components/button.css @@ -0,0 +1,131 @@ +.button { + display: inline-flex; + align-items: center; + justify-content: center; + height: 2rem; + gap: 0.5rem; + padding: 0.375rem 0.625rem; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + white-space: nowrap; + color: var(--primary-foreground); + background-color: var(--primary-background); + transition: colors 0.2s; + cursor: pointer; +} + +.button:disabled { + opacity: 0.5; + pointer-events: none; +} + +.button svg { + width: 1rem; + height: 1rem; + flex-shrink: 0; + pointer-events: none; +} + +/* Variants */ +.button:hover { + background-color: var(--primary-background-hover); +} + +.button--secondary { + color: var(--secondary-foreground); + background-color: var(--secondary-background); +} + +.button--secondary:hover { + background-color: var(--secondary-background-hover); +} + +.button--outline { + border: 1px solid var(--border); + color: var(--muted-foreground); + background-color: var(--background); +} + +.button--outline:hover { + background-color: var(--muted-background); +} + +.button--ghost { + color: var(--muted-foreground); + background-color: transparent; +} + +.button--ghost:hover { + background-color: var(--muted-background); +} + +/* Sizes */ +.button--sm { + height: 1.5rem; + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; +} + +.button--lg { + height: 2.5rem; + padding: 0.625rem 0.875rem; + border-radius: 0.5rem; +} + +.button--xl { + height: 3rem; + padding: 0.75rem 2rem; + border-radius: 0.5rem; + font-size: 1rem; +} + +.button--xl svg { + width: 1.25rem; + height: 1.25rem; +} + +.button--sm-icon { + width: 1.75rem; + height: 1.75rem; + padding: 0.25rem; + cursor: pointer; +} + +.button--sm-icon svg { + width: 1.25rem; + height: 1.25rem; +} + +.button--icon { + width: 2rem; + height: 2rem; + padding: 0.375rem; +} + +.button--icon svg { + width: 1.25rem; + height: 1.25rem; +} + +.button--lg-icon { + width: 2.25rem; + height: 2.25rem; + padding: 0.5rem; +} + +.button--lg-icon svg { + width: 1.25rem; + height: 1.25rem; +} + +.button--xl-icon { + width: 2.5rem; + height: 2.5rem; + padding: 0.5rem; +} + +.button--xl-icon svg { + width: 1.5rem; + height: 1.5rem; +} diff --git a/public/css/3_components/cart.css b/public/css/3_components/cart.css new file mode 100644 index 0000000..5d66349 --- /dev/null +++ b/public/css/3_components/cart.css @@ -0,0 +1,114 @@ +.cart { + max-width: 36rem; + margin-left: auto; + margin-right: auto; +} + +.cart__title { + margin-bottom: 3rem; + font-size: 1.875rem; + font-weight: bold; + line-height: 2rem; + text-align: center; +} + +.cart__container { + display: flex; + flex-direction: column; + border: 1px solid var(--border); + border-radius: 0.75rem; +} + +.cart__item { + display: flex; + padding: 1.5rem; + gap: 1.5rem; + border-bottom: 1px solid var(--border); +} + +.cart__item-image { + width: 5rem; + border-radius: 0.75rem; + background-color: var(--muted-background); +} + +.cart__item-image-content { + width: 100%; + aspect-ratio: 2/3; + object-fit: contain; +} + +.cart__item-details { + display: flex; + flex-direction: column; + justify-content: space-between; + flex-grow: 1; +} + +.cart__item-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.cart__item-title { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.cart__item-footer { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.cart__item-price { + font-size: 0.875rem; + font-weight: 500; + line-height: 1.25rem; +} + +.cart__item-quantity { + display: flex; + align-items: center; + gap: 1rem; +} + +.cart__item-quantity-display { + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + padding: 0.5rem 1rem; + border: 1px solid var(--border); + border-radius: 0.375rem; +} + +.cart__total { + display: flex; + justify-content: space-between; + padding: 1.5rem; + border-bottom: 1px solid var(--border); + font-size: 1rem; + font-weight: 500; + line-height: 1.5rem; +} + +.cart__action { + padding: 1.5rem; +} + +.cart__action-button { + width: 100%; +} + +@media (min-width: 48rem) { + .cart__item-footer { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} diff --git a/public/css/3_components/categories.css b/public/css/3_components/categories.css new file mode 100644 index 0000000..398f877 --- /dev/null +++ b/public/css/3_components/categories.css @@ -0,0 +1,50 @@ +.categories { + padding-top: 3rem; + padding-bottom: 3rem; +} + +.categories__header { + max-width: 48rem; +} + +.categories__title { + font-size: 1.5rem; + line-height: 2rem; + font-weight: bold; + margin-bottom: 1rem; +} + +.categories__description { + color: var(--muted-foreground); + margin-bottom: 2.5rem; +} + +.categories__description-break { + display: none; +} + +.categories__grid { + display: flex; + flex-direction: column; + gap: 2rem; +} + +@media (min-width: 768px) { + .categories { + padding-top: 6rem; + padding-bottom: 6rem; + } + + .categories__title { + font-size: 2.25rem; + line-height: 2.5rem; + } + + .categories__description-break { + display: block; + } + + .categories__grid { + flex-direction: row; + } +} diff --git a/public/css/3_components/category-header.css b/public/css/3_components/category-header.css new file mode 100644 index 0000000..a50a74b --- /dev/null +++ b/public/css/3_components/category-header.css @@ -0,0 +1,20 @@ +.category-header { + padding-top: 2.5rem; + padding-bottom: 2.5rem; + border-bottom: 1px solid var(--border); +} + +.category-header__content { + max-width: 48rem; +} + +.category-header__title { + font-size: 2.25rem; + font-weight: bold; + margin-bottom: 1rem; +} + +.category-header__description { + font-size: 0.875rem; + color: var(--muted-foreground); +} diff --git a/public/css/3_components/category.css b/public/css/3_components/category.css new file mode 100644 index 0000000..d646e46 --- /dev/null +++ b/public/css/3_components/category.css @@ -0,0 +1,31 @@ +.category { + flex: 1; + flex-basis: 0; +} + +.category__image { + border-radius: 0.75rem; + overflow: hidden; + margin-bottom: 1rem; +} + +.category__image img { + width: 100%; + aspect-ratio: 3/2; + object-fit: cover; +} + +.category__title { + font-weight: 600; + margin-bottom: 0.5rem; +} + +.category:hover .category__title { + text-decoration: underline; +} + +.category__description { + font-size: 0.875rem; + line-height: 1.25rem; + color: var(--muted-foreground); +} diff --git a/public/css/3_components/checkout.css b/public/css/3_components/checkout.css new file mode 100644 index 0000000..4051494 --- /dev/null +++ b/public/css/3_components/checkout.css @@ -0,0 +1,136 @@ +.checkout { + background-color: var(--muted-background); +} + +.checkout__layout { + display: flex; + flex-direction: column; + gap: 3rem; + max-width: 42rem; + margin-left: auto; + margin-right: auto; +} + +.checkout__summary { + flex-grow: 1; +} + +.checkout__summary_title { + margin-bottom: 1rem; + font-size: 1.125rem; + font-weight: 500; + line-height: 1.75rem; +} + +.checkout__summary_container { + display: flex; + flex-direction: column; + border: 1px solid var(--border); + border-radius: 0.75rem; + background-color: var(--background); +} + +.checkout__item { + display: flex; + padding: 1.5rem; + gap: 1.5rem; + border-bottom: 1px solid var(--border); +} + +.checkout__item-image { + width: 5rem; + border-radius: 0.75rem; + background-color: var(--muted-background); +} + +.checkout__item-image-content { + width: 100%; + aspect-ratio: 1; + object-fit: contain; +} + +.checkout__item-details { + display: flex; + flex-direction: column; + justify-content: space-between; + flex-grow: 1; +} + +.checkout__item-title { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.checkout__item-price { + display: flex; + align-items: center; + align-self: flex-end; + gap: 1rem; + font-size: 0.875rem; + font-weight: 500; + line-height: 1.25rem; +} + +.checkout__item-price-icon { + width: 1rem; + height: 1rem; +} + +.checkout__total { + display: flex; + justify-content: space-between; + padding: 1.5rem; + font-size: 1rem; + font-weight: 500; + line-height: 1.5rem; +} + +.checkout__form { + flex-grow: 1; + + fieldset { + display: block; + width: 100%; + } +} + +.checkout__legend { + margin-bottom: 1.5rem; + font-size: 1.25rem; + font-weight: 500; + line-height: 1.75rem; +} + +.checkout__separator { + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + +.checkout__form-fields { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.checkout__submit { + width: 100%; + margin-top: 1.5rem; +} + +@media (min-width: 64rem) { + .checkout__layout { + flex-direction: row; + max-width: none; + align-items: start; + } + + .checkout__form { + order: -1; + max-width: 56rem; + } + + .checkout__summary { + position: sticky; + top: calc(96px + 49px); + } +} diff --git a/public/css/3_components/error.css b/public/css/3_components/error.css new file mode 100644 index 0000000..7da9ce8 --- /dev/null +++ b/public/css/3_components/error.css @@ -0,0 +1,20 @@ +/* +.error { +} +*/ + +.error__content { + text-align: center; +} + +.error__title { + margin-bottom: 0.75rem; + font-size: 1.5rem; + font-weight: 700; + color: tomato; +} + +.error__message { + margin-bottom: 1rem; + color: var(--muted-foreground); +} diff --git a/public/css/3_components/features.css b/public/css/3_components/features.css new file mode 100644 index 0000000..9bc141f --- /dev/null +++ b/public/css/3_components/features.css @@ -0,0 +1,54 @@ +.features { + padding-top: 3rem; + padding-bottom: 3rem; + text-align: center; + background-color: var(--muted-background); +} + +.features__title { + margin-bottom: 3rem; + font-size: 1.5rem; + font-weight: bold; +} + +.features__grid { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.feature__icon { + display: inline-block; + margin-bottom: 1.5rem; +} + +.feature__title { + margin-bottom: 0.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +.feature__description { + font-size: 0.875rem; + line-height: 1.25rem; + color: var(--muted-foreground); +} + +@media (min-width: 640px) { + .features__grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 768px) { + .features { + padding-top: 6rem; + padding-bottom: 6rem; + } + + .features__grid { + grid-template-columns: repeat(4, 1fr); + } +} diff --git a/public/css/3_components/footer.css b/public/css/3_components/footer.css new file mode 100644 index 0000000..c4df0b4 --- /dev/null +++ b/public/css/3_components/footer.css @@ -0,0 +1,69 @@ +/* .footer { +} */ + +.footer__section { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.footer__links { + display: flex; + flex-wrap: wrap; + gap: 1rem 2rem; + flex-grow: 1; +} + +.footer__list { + flex: 1; + flex-basis: 10rem; + display: flex; + flex-direction: column; + gap: 1.5rem; + padding: 0; + font-size: 0.875rem; + color: var(--muted-foreground); +} + +.footer__title { + font-weight: 500; + color: var(--foreground); +} + +.footer__newsletter { + max-width: 28rem; + font-size: 0.875rem; +} + +.footer__newsletter-title { + margin-bottom: 1.5rem; + font-weight: 500; +} + +.footer__newsletter-text { + margin-bottom: 0.5rem; + color: var(--muted-foreground); +} + +.footer__form { + display: flex; + gap: 0.5rem; + + input { + flex-grow: 1; + } +} + +.footer__copyright { + display: block; + padding: 1.5rem 0; + font-size: 0.875rem; + text-align: center; + color: var(--muted-foreground); +} + +@media (min-width: 64rem) { + .footer__section { + flex-direction: row; + } +} diff --git a/public/css/3_components/header-actions.css b/public/css/3_components/header-actions.css new file mode 100644 index 0000000..3f1203e --- /dev/null +++ b/public/css/3_components/header-actions.css @@ -0,0 +1,28 @@ +.header-actions { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.header-actions__separator { + height: 1.5rem; +} + +.header-actions__cart { + position: relative; +} + +.header-actions__cart-badge { + position: absolute; + bottom: -0.25rem; + right: -0.25rem; + display: flex; + align-items: center; + justify-content: center; + width: 1.25rem; + height: 1.25rem; + border-radius: 9999px; + font-size: 0.75rem; + color: var(--primary-foreground); + background-color: var(--primary-background); +} diff --git a/public/css/3_components/header-main.css b/public/css/3_components/header-main.css new file mode 100644 index 0000000..2bf6aee --- /dev/null +++ b/public/css/3_components/header-main.css @@ -0,0 +1,26 @@ +.header-main { + position: relative; +} + +.header-main__top { + display: flex; + justify-content: space-between; + align-items: center; + height: 3rem; +} + +.header-main__separator { + display: none; +} + +@media (min-width: 40rem) { + .header-main { + position: relative; + } +} + +@media (max-width: 639px) { + .header-main__separator { + display: block; + } +} diff --git a/public/css/3_components/hero.css b/public/css/3_components/hero.css new file mode 100644 index 0000000..f756eec --- /dev/null +++ b/public/css/3_components/hero.css @@ -0,0 +1,39 @@ +.hero { + text-align: center; + color: var(--white); + background-size: cover; + background-repeat: no-repeat; + background-position: center; + background-image: linear-gradient( + 0deg, + rgba(0, 0, 0, 0.5) 0%, + rgba(0, 0, 0, 0.5) 100% + ), + url("/images/hero.jpg"); +} + +.hero__container { + padding-top: 8rem; + padding-bottom: 8rem; + max-width: 48rem; +} + +.hero__title { + font-size: 2.25rem; + font-weight: bold; + margin-bottom: 1rem; + line-height: 2.5rem; +} + +.hero__text { + font-size: 1.25rem; + margin-bottom: 2rem; + line-height: 1.75rem; +} + +@media (min-width: 768px) { + .hero__title { + font-size: 3.75rem; + line-height: 1; + } +} diff --git a/public/css/3_components/input-field.css b/public/css/3_components/input-field.css new file mode 100644 index 0000000..e2aa924 --- /dev/null +++ b/public/css/3_components/input-field.css @@ -0,0 +1,5 @@ +.input-field { + display: flex; + flex-direction: column; + gap: 0.5rem; +} diff --git a/public/css/3_components/main-nav.css b/public/css/3_components/main-nav.css new file mode 100644 index 0000000..a89a83c --- /dev/null +++ b/public/css/3_components/main-nav.css @@ -0,0 +1,42 @@ +.main-nav { + position: static; +} + +.main-nav__list { + display: flex; + justify-content: center; + height: 3rem; +} + +.main-nav__item { + display: flex; + justify-content: center; +} + +.main-nav__link { + display: inline-flex; + justify-content: center; + align-items: center; + padding: 0.75rem; + font-size: 0.875rem; + font-weight: 500; + color: var(--muted-foreground); + transition: background-color 0.2s; +} + +.main-nav__link:hover { + background-color: var(--accent-background); +} + +.main-nav__link--active { + color: var(--accent-foreground); +} + +@media (min-width: 640px) { + .main-nav { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } +} diff --git a/public/css/3_components/not-found.css b/public/css/3_components/not-found.css new file mode 100644 index 0000000..d9d59e2 --- /dev/null +++ b/public/css/3_components/not-found.css @@ -0,0 +1,17 @@ +/* .not-found { +} */ + +.not-found__content { + text-align: center; +} + +.not-found__title { + margin-bottom: 0.75rem; + font-size: 1.5rem; + font-weight: 700; +} + +.not-found__message { + margin-bottom: 1rem; + color: var(--muted-foreground); +} diff --git a/public/css/3_components/order-confirmation.css b/public/css/3_components/order-confirmation.css new file mode 100644 index 0000000..2aa8c98 --- /dev/null +++ b/public/css/3_components/order-confirmation.css @@ -0,0 +1,51 @@ +.order-confirmation { + padding-top: 3rem; + padding-bottom: 3rem; +} + +.order-confirmation__title { + margin-bottom: 0.5rem; + font-size: 1rem; + color: var(--accent-foreground); + font-weight: 500; +} + +.order-confirmation__heading { + margin-bottom: 0.5rem; + font-size: 2.25rem; + line-height: 2.25rem; + font-weight: bold; +} + +.order-confirmation__description { + margin-bottom: 3rem; + color: var(--muted-foreground); +} + +.order-confirmation__tracking-label { + margin-bottom: 0.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +.order-confirmation__tracking-code { + color: var(--accent-foreground); + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +@media (min-width: 40rem) { + .order-confirmation { + padding-top: 3.5rem; + padding-bottom: 3.5rem; + } +} + +@media (min-width: 64rem) { + .order-confirmation { + padding-top: 4rem; + padding-bottom: 4rem; + } +} diff --git a/public/css/3_components/price-filter.css b/public/css/3_components/price-filter.css new file mode 100644 index 0000000..ee02589 --- /dev/null +++ b/public/css/3_components/price-filter.css @@ -0,0 +1,33 @@ +.price-filter { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.price-filter__legend { + font-size: 1rem; + line-height: 1.5rem; + font-weight: 500; + margin-bottom: 1rem; +} + +.price-filter__inputs { + display: flex; + gap: 1.5rem; +} + +.price-filter__field { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.price-filter__label { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +.price-filter__button { + width: 100%; +} diff --git a/public/css/3_components/product-card.css b/public/css/3_components/product-card.css new file mode 100644 index 0000000..8b26b20 --- /dev/null +++ b/public/css/3_components/product-card.css @@ -0,0 +1,70 @@ +.product-card { + display: block; + border-radius: 0.75rem; +} + +.product-card__container { + position: relative; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + border: 1px solid var(--separator); + border-radius: 0.75rem; +} + +.product-card__image-container { + aspect-ratio: 3/4; + background-color: var(--muted-background); +} + +.product-card__image { + width: 100%; + height: 100%; + object-fit: contain; + transition: transform 0.2s; +} + +:is(.product-card:hover, .product-card:focus-visible) .product-card__image { + transform: scale(1.05); +} + +.product-card__content { + display: flex; + flex-direction: column; + flex-grow: 1; + gap: 0.5rem; + padding: 1rem; +} + +.product-card__title { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +.product-card__description { + font-size: 0.875rem; + line-height: 1.25rem; + color: var(--muted-foreground); +} + +.product-card__price { + margin-top: auto; + font-size: 1rem; + line-height: 1.5rem; + font-weight: 500; +} + +.product-card__sale-badge { + position: absolute; + top: 0; + right: 0; + padding: 0.25rem 0.5rem; + border-bottom-left-radius: 0.75rem; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; + color: var(--primary-foreground); + background-color: var(--primary-background); +} diff --git a/public/css/3_components/product.css b/public/css/3_components/product.css new file mode 100644 index 0000000..c2d5698 --- /dev/null +++ b/public/css/3_components/product.css @@ -0,0 +1,92 @@ +.product { + padding-top: 3rem; + padding-bottom: 3rem; +} + +.product__container { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.product__image { + background-color: var(--muted-background); + border-radius: 0.75rem; + min-width: min(100%, 28rem); + align-self: center; + flex-basis: 0; + flex-grow: 1; + max-width: 36rem; +} + +.product__image_content { + width: 100%; + aspect-ratio: 1; + object-fit: contain; +} + +.product__info { + flex-grow: 1; + flex-basis: 0; +} + +.product__title { + font-size: 1.875rem; + line-height: 2.25rem; + font-weight: bold; + margin-bottom: 0.75rem; +} + +.product__price { + font-size: 1.875rem; + line-height: 2.25rem; + margin-bottom: 1.5rem; +} + +.product__description { + font-size: 0.875rem; + line-height: 1.25rem; + color: var(--muted-foreground); + margin-bottom: 2.5rem; +} + +.product__button { + width: 100%; +} + +.product__separator { + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + +.product__features_title { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 600; + color: var(--accent-foreground); + margin-bottom: 1.5rem; +} + +.product__features_list { + list-style-type: disc; + padding-left: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; + color: var(--muted-foreground); +} + +@media (min-width: 48rem) { + .product__container { + flex-direction: row; + align-items: flex-start; + } + + .product__image { + min-width: fit-content; + align-self: flex-start; + } + + .product__button { + width: 20rem; + } +} diff --git a/public/css/3_components/products.css b/public/css/3_components/products.css new file mode 100644 index 0000000..2bae9e0 --- /dev/null +++ b/public/css/3_components/products.css @@ -0,0 +1,32 @@ +.products { + padding-top: 2.5rem; + padding-bottom: 2.5rem; +} + +.products__layout { + display: flex; + gap: 2rem; + flex-direction: column; +} + +.products__price-filter { + width: 100%; + max-width: 24rem; +} + +.products__grid { + display: grid; + gap: 2rem; + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + flex-grow: 1; +} + +@media (min-width: 64rem) { + .products__layout { + flex-direction: row; + } + + .products__price-filter { + max-width: 20rem; + } +} diff --git a/public/css/3_components/prose.css b/public/css/3_components/prose.css new file mode 100644 index 0000000..bc836da --- /dev/null +++ b/public/css/3_components/prose.css @@ -0,0 +1,218 @@ +/* Content */ + +.prose { + --headings: var(--foreground); + --body: var(--foreground); + --captions: var(--muted-foreground); + --bold: var(--foreground); + --code: var(--foreground); + --pre: var(--muted); + --pre-background: var(--foreground); + --hr: var(--border); + --td-border: var(--border); + --th-border: var(--border); + --links: var(--accent-foreground); + --markers: var(--accent-foreground); +} + +.prose { + color: var(--body); + font-size: 1rem; /* 16px */ + line-height: 1.75rem; /* 28px */ +} + +.prose h1 { + margin-top: 0; + margin-bottom: 2rem; /* 32px */ + + color: var(--headings); + font-weight: 800; + font-size: 2.25rem; /* 36px */ + line-height: 2.5rem; /* 40px */ +} + +.prose h2 { + margin-top: 3rem; /* 48px */ + margin-bottom: 1.5rem; /* 24px */ + + color: var(--headings); + font-weight: 700; + font-size: 1.5rem; /* 24px */ + line-height: 2rem; /* 32px */ +} + +.prose h3 { + margin-top: 2rem; /* 32px */ + margin-bottom: 0.75rem; /* 12px */ + + color: var(--headings); + font-weight: 600; + font-size: 1.25rem; /* 20px */ + line-height: 2rem; /* 32px */ +} + +.prose h4 { + margin-top: 1.5rem; /* 24px */ + margin-bottom: 0.5rem; /* 8px */ + + color: var(--headings); + font-weight: 600; + font-size: 1rem; /* 16px */ + line-height: 1.5rem; /* 24px */ +} + +.prose img { + display: block; + max-width: 100%; + height: auto; + margin-block: 2rem; /* 32px */ + border-radius: 0.375rem; /* 6px */ +} + +.prose figure { + margin-block: 2rem; /* 32px */ +} + +.prose figure img { + margin-block: 0; +} + +.prose figure figcaption { + margin-top: 0.75rem; /* 12px */ + margin-bottom: 0; + + color: var(--captions); + font-size: 0.875rem; /* 14px */ + line-height: 1.25rem; /* 20px */ +} + +.prose ol, +.prose ul { + margin-block: 1.25rem; /* 20px */ + padding-left: 32px; +} + +.prose li { + margin-block: 0.5rem; /* 8px */ +} + +.prose li::marker { + color: var(--markers); +} + +.prose li p { + margin-block: 0.75rem; /* 12px */ +} + +.prose hr { + margin-block: 3rem; /* 48px */ +} + +.prose p { + margin-block: 1.25rem; /* 20px */ +} + +.prose strong { + color: var(--bold); + font-weight: 600; +} + +.prose a { + color: var(--links); + font-weight: 500; +} + +.prose code { + color: var(--code); + font-family: var(--monospace); + font-size: 0.875rem; /* 14px */ + font-weight: 600; + line-height: 1.75rem; /* 28px */ +} + +.prose code::before, +.prose code::after { + content: "`"; +} + +.prose pre { + margin-block: 1.5rem; /* 24px */ + padding: 12px 16px; + background: var(--pre-background); + border-radius: 0.375rem; /* 6px */ + overflow: auto; + + color: var(--pre); + font-family: var(--monospace); + font-size: 0.875rem; /* 14px */ + line-height: 1.75rem; /* 28px */ +} + +.prose pre code { + all: unset; +} + +.prose pre code::before, +.prose pre code::after { + content: unset; +} + +.prose table { + margin-block: 2rem; /* 32px */ + width: 100%; + text-align: left; + border-collapse: collapse; +} + +.prose th { + padding: 0 8px 8px; + + color: var(--headings); + font-size: 0.875rem; /* 14px */ + font-weight: 600; + line-height: 1.75rem; /* 28px */ +} + +.prose th:first-child, +.prose td:first-child { + padding-left: 0; +} + +.prose th:last-child, +.prose td:last-child { + padding-right: 0; +} + +.prose td { + padding: 8px; + + font-size: 0.875rem; /* 14px */ + font-weight: 400; + line-height: 1.75rem; /* 28px */ +} + +.prose th { + border-bottom: 1px solid var(--th-border); +} + +.prose td { + border-bottom: 1px solid var(--td-border); +} + +.prose tr:last-child td { + border-bottom: unset; +} + +.prose h2 + *, +.prose h3 + *, +.prose h4 + * { + margin-top: 0; +} + +.prose > *:first-child { + margin-top: 0; +} + +.prose > *:last-child { + margin-bottom: 0; +} diff --git a/public/css/3_components/root.css b/public/css/3_components/root.css new file mode 100644 index 0000000..d03ad6f --- /dev/null +++ b/public/css/3_components/root.css @@ -0,0 +1,18 @@ +.root { + display: grid; + grid-template-rows: auto 1fr auto; + min-height: 100vh; + background-color: var(--background); +} + +.root__header { + position: sticky; + top: 0; + z-index: 50; + border-bottom: 1px solid var(--border); + background-color: var(--background); +} + +.root__footer { + border-top: 1px solid var(--border); +} diff --git a/public/css/3_components/separator.css b/public/css/3_components/separator.css new file mode 100644 index 0000000..d399589 --- /dev/null +++ b/public/css/3_components/separator.css @@ -0,0 +1,12 @@ +.separator { + flex-shrink: 0; + width: 100%; + height: 1px; + + background-color: var(--border); +} + +.separator--vertical { + width: 1px; + height: 100%; +} diff --git a/public/css/index.css b/public/css/index.css new file mode 100644 index 0000000..a8966c8 --- /dev/null +++ b/public/css/index.css @@ -0,0 +1,43 @@ +/* Declare layers in cascade order */ +@layer definitions, reset, global, layouts, components, utilities; + +/* 1 Foundation */ +@import "1_foundation/colors.css" layer(definitions); +@import "1_foundation/typography.css" layer(definitions); +@import "1_foundation/reset.css" layer(reset); +@import "1_foundation/global.css" layer(global); + +/* 2 Layouts */ +@import "2_layouts/container.css" layer(layouts); +@import "2_layouts/section.css" layer(layouts); + +/* 3 Components */ +/* UI */ +@import "3_components/button.css" layer(components); +@import "3_components/separator.css" layer(components); +@import "3_components/input-field.css" layer(components); + +/* Routes */ +@import "3_components/not-found.css" layer(components); +@import "3_components/error.css" layer(components); +@import "3_components/root.css" layer(components); +@import "3_components/footer.css" layer(components); +@import "3_components/header-main.css" layer(components); +@import "3_components/header-actions.css" layer(components); +@import "3_components/main-nav.css" layer(components); +@import "3_components/categories.css" layer(components); +@import "3_components/category.css" layer(components); +@import "3_components/features.css" layer(components); +@import "3_components/hero.css" layer(components); +@import "3_components/category-header.css" layer(components); +@import "3_components/products.css" layer(components); +@import "3_components/price-filter.css" layer(components); +@import "3_components/product-card.css" layer(components); +@import "3_components/product.css" layer(components); +@import "3_components/cart.css" layer(components); +@import "3_components/checkout.css" layer(components); +@import "3_components/order-confirmation.css" layer(components); +@import "3_components/prose.css" layer(components); + +/* 4 Utilities */ +/* @import "4_utilities/__.css" layer(utilities); */ diff --git a/public/gatito.png b/public/gatito.png deleted file mode 100644 index 0749e6f..0000000 Binary files a/public/gatito.png and /dev/null differ diff --git a/public/home.html b/public/home.html new file mode 100644 index 0000000..388b8dd --- /dev/null +++ b/public/home.html @@ -0,0 +1,259 @@ + + + + + + Full Stock | Inicio + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+

Nuevos productos disponibles

+

+ Un pequeño lote de increíbles productos acaba de llegar. +
+ Agrega tus favoritos al carrito antes que se agoten. +

+ Compra ahora +
+
+ +
+ +
+ +
+
+

Nuestra Promesa de Calidad

+
+
+ +

Entrega rápida

+

+ Recibe tus productos en tiempo récord, directo a tu puerta, + para que puedas disfrutar de ellos cuanto antes. +

+
+ +
+ +

Satisfacción Garantizada

+

+ Tu felicidad es nuestra prioridad. Si no estás 100% + satisfecho, estamos aquí para ayudarte con cambios o + devoluciones. +

+
+ +
+ +

Materiales de Alta Calidad

+

+ Nos aseguramos de que todos nuestros productos estén hechos + con materiales de la más alta calidad. +

+
+ +
+ +

Diseños Exclusivos

+

+ Cada producto está diseñado pensando en los desarrolladores, + con estilos únicos que no encontrarás en ningún otro lugar. +

+
+
+
+
+
+ +
+ + diff --git a/public/image.png b/public/image.png deleted file mode 100644 index 6ef6fcc..0000000 Binary files a/public/image.png and /dev/null differ diff --git a/public/images/fullstock-logo.svg b/public/images/fullstock-logo.svg new file mode 100644 index 0000000..0f16800 --- /dev/null +++ b/public/images/fullstock-logo.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/hero.jpg b/public/images/hero.jpg new file mode 100644 index 0000000..e97876c Binary files /dev/null and b/public/images/hero.jpg differ diff --git a/public/images/icons/cart.svg b/public/images/icons/cart.svg new file mode 100644 index 0000000..3b3e1fa --- /dev/null +++ b/public/images/icons/cart.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/public/images/icons/idea.svg b/public/images/icons/idea.svg new file mode 100644 index 0000000..6dde41d --- /dev/null +++ b/public/images/icons/idea.svg @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/images/icons/minus.svg b/public/images/icons/minus.svg new file mode 100644 index 0000000..8c2ee74 --- /dev/null +++ b/public/images/icons/minus.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/public/images/icons/plus.svg b/public/images/icons/plus.svg new file mode 100644 index 0000000..cb53d86 --- /dev/null +++ b/public/images/icons/plus.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/return.svg b/public/images/icons/return.svg new file mode 100644 index 0000000..027087b --- /dev/null +++ b/public/images/icons/return.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/public/images/icons/ribbon.svg b/public/images/icons/ribbon.svg new file mode 100644 index 0000000..4eac618 --- /dev/null +++ b/public/images/icons/ribbon.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/public/images/icons/trash.svg b/public/images/icons/trash.svg new file mode 100644 index 0000000..0560c9d --- /dev/null +++ b/public/images/icons/trash.svg @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/public/images/icons/truck.svg b/public/images/icons/truck.svg new file mode 100644 index 0000000..c70699e --- /dev/null +++ b/public/images/icons/truck.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/public/images/icons/x.svg b/public/images/icons/x.svg new file mode 100644 index 0000000..cfafac6 --- /dev/null +++ b/public/images/icons/x.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/public/images/polos.jpg b/public/images/polos.jpg new file mode 100644 index 0000000..925630f Binary files /dev/null and b/public/images/polos.jpg differ diff --git a/public/images/polos/polo-backend.png b/public/images/polos/polo-backend.png new file mode 100644 index 0000000..7cf4eb9 Binary files /dev/null and b/public/images/polos/polo-backend.png differ diff --git a/public/images/polos/polo-feature.png b/public/images/polos/polo-feature.png new file mode 100644 index 0000000..cd5baa5 Binary files /dev/null and b/public/images/polos/polo-feature.png differ diff --git a/public/images/polos/polo-frontend.png b/public/images/polos/polo-frontend.png new file mode 100644 index 0000000..fd60002 Binary files /dev/null and b/public/images/polos/polo-frontend.png differ diff --git a/public/images/polos/polo-fullstack.png b/public/images/polos/polo-fullstack.png new file mode 100644 index 0000000..9f72803 Binary files /dev/null and b/public/images/polos/polo-fullstack.png differ diff --git a/public/images/polos/polo-js.png b/public/images/polos/polo-js.png new file mode 100644 index 0000000..6736016 Binary files /dev/null and b/public/images/polos/polo-js.png differ diff --git a/public/images/polos/polo-node.png b/public/images/polos/polo-node.png new file mode 100644 index 0000000..b89ad3f Binary files /dev/null and b/public/images/polos/polo-node.png differ diff --git a/public/images/polos/polo-react.png b/public/images/polos/polo-react.png new file mode 100644 index 0000000..01e0e41 Binary files /dev/null and b/public/images/polos/polo-react.png differ diff --git a/public/images/polos/polo-ts.png b/public/images/polos/polo-ts.png new file mode 100644 index 0000000..8638555 Binary files /dev/null and b/public/images/polos/polo-ts.png differ diff --git a/public/images/polos/polo-works.png b/public/images/polos/polo-works.png new file mode 100644 index 0000000..89b3907 Binary files /dev/null and b/public/images/polos/polo-works.png differ diff --git a/public/images/stickers.jpg b/public/images/stickers.jpg new file mode 100644 index 0000000..13b90ba Binary files /dev/null and b/public/images/stickers.jpg differ diff --git a/public/images/stickers/sticker-docker.png b/public/images/stickers/sticker-docker.png new file mode 100644 index 0000000..3b16a70 Binary files /dev/null and b/public/images/stickers/sticker-docker.png differ diff --git a/public/images/stickers/sticker-git.png b/public/images/stickers/sticker-git.png new file mode 100644 index 0000000..670da23 Binary files /dev/null and b/public/images/stickers/sticker-git.png differ diff --git a/public/images/stickers/sticker-github.png b/public/images/stickers/sticker-github.png new file mode 100644 index 0000000..53cc3d5 Binary files /dev/null and b/public/images/stickers/sticker-github.png differ diff --git a/public/images/stickers/sticker-html.png b/public/images/stickers/sticker-html.png new file mode 100644 index 0000000..bbce95d Binary files /dev/null and b/public/images/stickers/sticker-html.png differ diff --git a/public/images/stickers/sticker-js.png b/public/images/stickers/sticker-js.png new file mode 100644 index 0000000..32b72c3 Binary files /dev/null and b/public/images/stickers/sticker-js.png differ diff --git a/public/images/stickers/sticker-linux.png b/public/images/stickers/sticker-linux.png new file mode 100644 index 0000000..a92a548 Binary files /dev/null and b/public/images/stickers/sticker-linux.png differ diff --git a/public/images/stickers/sticker-react.png b/public/images/stickers/sticker-react.png new file mode 100644 index 0000000..45f1dd5 Binary files /dev/null and b/public/images/stickers/sticker-react.png differ diff --git a/public/images/stickers/sticker-vscode.png b/public/images/stickers/sticker-vscode.png new file mode 100644 index 0000000..5b3bc77 Binary files /dev/null and b/public/images/stickers/sticker-vscode.png differ diff --git a/public/images/tazas.jpg b/public/images/tazas.jpg new file mode 100644 index 0000000..583b47e Binary files /dev/null and b/public/images/tazas.jpg differ diff --git a/public/images/tazas/taza-git.png b/public/images/tazas/taza-git.png new file mode 100644 index 0000000..f30284a Binary files /dev/null and b/public/images/tazas/taza-git.png differ diff --git a/public/images/tazas/taza-github.png b/public/images/tazas/taza-github.png new file mode 100644 index 0000000..5de43f1 Binary files /dev/null and b/public/images/tazas/taza-github.png differ diff --git a/public/images/tazas/taza-js.png b/public/images/tazas/taza-js.png new file mode 100644 index 0000000..968652d Binary files /dev/null and b/public/images/tazas/taza-js.png differ diff --git a/public/images/tazas/taza-linux.png b/public/images/tazas/taza-linux.png new file mode 100644 index 0000000..807339e Binary files /dev/null and b/public/images/tazas/taza-linux.png differ diff --git a/public/images/tazas/taza-react.png b/public/images/tazas/taza-react.png new file mode 100644 index 0000000..6f242e7 Binary files /dev/null and b/public/images/tazas/taza-react.png differ diff --git a/public/images/tazas/taza-sql.png b/public/images/tazas/taza-sql.png new file mode 100644 index 0000000..f69a69a Binary files /dev/null and b/public/images/tazas/taza-sql.png differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index d2b9608..0000000 --- a/public/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - FullStock MPA - - - -

Welcome to FullStock MPA

-

This is the home page.

- Un gatito lindo - - diff --git a/public/layout.html b/public/layout.html new file mode 100644 index 0000000..91c8422 --- /dev/null +++ b/public/layout.html @@ -0,0 +1,136 @@ + + + + + + Full Stock | Inicio + + + + + + + + + +
+
+
+ +
+ +
+
+
+ +
+ +
+ + diff --git a/public/nombres.json b/public/nombres.json deleted file mode 100644 index 664f3e5..0000000 --- a/public/nombres.json +++ /dev/null @@ -1 +0,0 @@ -["Ana", "Luis", "María", "Carlos", "Sofía", "Javier"] diff --git a/public/order-confirmation.html b/public/order-confirmation.html new file mode 100644 index 0000000..3ddddbf --- /dev/null +++ b/public/order-confirmation.html @@ -0,0 +1,148 @@ + + + + + + Full Stock | Inicio + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+

+ ¡Muchas gracias por tu compra! +

+

Tu orden está en camino

+

+ Llegaremos a la puerta de tu domicilio lo antes posible +

+

Número de orden

+

1

+
+
+
+ +
+ + diff --git a/public/product.html b/public/product.html new file mode 100644 index 0000000..0a6bb3d --- /dev/null +++ b/public/product.html @@ -0,0 +1,174 @@ + + + + + + Full Stock | Polo React + + + + + + + + + +
+
+
+ +
+ +
+
+
+
+
+
+ Polo React +
+
+

Polo React

+

S/ 20

+

+ Viste tu pasión por React con estilo y comodidad en cada línea + de código. +

+
+ +
+
+
+

Características

+
    +
  • + Estampado resistente que mantiene sus colores vibrantes + lavado tras lavado. +
  • +
  • + Hecho de algodón suave que asegura comodidad y frescura. +
  • +
  • Costuras reforzadas para una mayor durabilidad.
  • +
  • Corte moderno que se adapta perfectamente al cuerpo.
  • +
+
+
+
+
+
+ +
+ + diff --git a/public/style.css b/public/style.css deleted file mode 100644 index fcb472e..0000000 --- a/public/style.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - color: tomato; -} diff --git a/public/terms.html b/public/terms.html deleted file mode 100644 index 0c07f24..0000000 --- a/public/terms.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Terminos y Condiciones - - - -

Terminos y Condiciones

- - diff --git a/template-system.md b/template-system.md new file mode 100644 index 0000000..74eb96d --- /dev/null +++ b/template-system.md @@ -0,0 +1,54 @@ +# ¿Qué es un Sistema de Plantillas en Server Side Rendering? + +Un **sistema de plantillas** es una herramienta que permite generar páginas HTML dinámicas a partir de datos y estructuras predefinidas. En el contexto de **server side rendering (SSR)**, el servidor utiliza estas plantillas para crear el HTML final antes de enviarlo al navegador del usuario. + +## ¿Por qué usar un sistema de plantillas? +- **Separación de lógica y presentación:** Permite mantener el código de la aplicación separado del diseño visual. +- **Reutilización:** Puedes definir fragmentos reutilizables (headers, footers, etc.) y usarlos en múltiples páginas. +- **Dinamicidad:** El contenido de la página se puede adaptar según los datos recibidos del servidor. + +## Ejemplo: EJS (Embedded JavaScript Templates) + +**EJS** es uno de los sistemas de plantillas más populares en el ecosistema de Node.js. Permite incrustar código JavaScript dentro de archivos HTML usando la sintaxis `<%= %>` para imprimir valores y `<% %>` para ejecutar lógica. + +### Ejemplo básico de EJS +Supongamos que tienes una plantilla `index.ejs`: + +```ejs + + + + <%= title %> + + +

Bienvenido, <%= user.name %>!

+ + + +``` + +Y en tu servidor Node.js: + +```js +app.get('/', (req, res) => { + res.render('index', { + title: 'Tienda Online', + user: { name: 'Diego' }, + products: [ + { name: 'Taza', price: 10 }, + { name: 'Sticker', price: 5 } + ] + }); +}); +``` + +El servidor procesa la plantilla, reemplaza las variables y genera el HTML final que se envía al cliente. + +## Ventajas de EJS en SSR +- Fácil de aprender y usar. +- Permite lógica sencilla dentro de la plantilla. +- Integración directa con Express y otros frameworks de Node.js. diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..8098744 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,18 @@ + + + + + + Document + + +

Welcome to the EJS Template

+

<%= nombre %>

+ <% console.log("Hola desde EJS") %> + + +