feat: init project SelfChckout
This commit is contained in:
parent
765cc0c7cf
commit
9d31ea245c
62 changed files with 8869 additions and 7149 deletions
|
|
@ -3,9 +3,7 @@
|
||||||
"projectOwner": "Blazity",
|
"projectOwner": "Blazity",
|
||||||
"repoType": "github",
|
"repoType": "github",
|
||||||
"repoHost": "https://github.com",
|
"repoHost": "https://github.com",
|
||||||
"files": [
|
"files": ["README.md"],
|
||||||
"README.md"
|
|
||||||
],
|
|
||||||
"imageSize": 100,
|
"imageSize": 100,
|
||||||
"commit": true,
|
"commit": true,
|
||||||
"commitConvention": "angular",
|
"commitConvention": "angular",
|
||||||
|
|
@ -15,27 +13,21 @@
|
||||||
"name": "Bart Stefanski",
|
"name": "Bart Stefanski",
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/28964599?v=4",
|
"avatar_url": "https://avatars.githubusercontent.com/u/28964599?v=4",
|
||||||
"profile": "https://bstefanski.com/",
|
"profile": "https://bstefanski.com/",
|
||||||
"contributions": [
|
"contributions": ["code"]
|
||||||
"code"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"login": "jjablonski-it",
|
"login": "jjablonski-it",
|
||||||
"name": "Jakub Jabłoński",
|
"name": "Jakub Jabłoński",
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/51968772?v=4",
|
"avatar_url": "https://avatars.githubusercontent.com/u/51968772?v=4",
|
||||||
"profile": "https://github.com/jjablonski-it",
|
"profile": "https://github.com/jjablonski-it",
|
||||||
"contributions": [
|
"contributions": ["infra"]
|
||||||
"infra"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"login": "neg4n",
|
"login": "neg4n",
|
||||||
"name": "Igor Klepacki",
|
"name": "Igor Klepacki",
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/57688858?v=4",
|
"avatar_url": "https://avatars.githubusercontent.com/u/57688858?v=4",
|
||||||
"profile": "https://neg4n.dev/",
|
"profile": "https://neg4n.dev/",
|
||||||
"contributions": [
|
"contributions": ["doc"]
|
||||||
"doc"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
.next
|
.next
|
||||||
node_modules
|
node_modules
|
||||||
68
.gitignore
vendored
68
.gitignore
vendored
|
|
@ -1,35 +1,35 @@
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
node_modules
|
node_modules
|
||||||
.pnp
|
.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
coverage
|
coverage
|
||||||
|
|
||||||
# next.js
|
# next.js
|
||||||
.next/
|
.next/
|
||||||
out/
|
out/
|
||||||
build
|
build
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.pem
|
*.pem
|
||||||
|
|
||||||
# debug
|
# debug
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
.pnpm-debug.log*
|
.pnpm-debug.log*
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
|
|
||||||
/.npm-only-allow
|
/.npm-only-allow
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
.next
|
.next
|
||||||
node_modules
|
node_modules
|
||||||
24
.releaserc
24
.releaserc
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
branches: ["main"],
|
branches: ["main"],
|
||||||
"plugins":
|
"plugins":
|
||||||
[
|
[
|
||||||
["@semantic-release/npm", { "npmPublish": false }],
|
["@semantic-release/npm", { "npmPublish": false }],
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/github",
|
"@semantic-release/github",
|
||||||
"@semantic-release/commit-analyzer",
|
"@semantic-release/commit-analyzer",
|
||||||
"@semantic-release/git",
|
"@semantic-release/git",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
LICENSE
42
LICENSE
|
|
@ -1,21 +1,21 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023 Blazity
|
Copyright (c) 2023 Blazity
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
<img align="right" width="360px" height="410px" src="./.github/assets/project-logo-vertical.png">
|
<img align="right" width="360px" height="410px" src="./.github/assets/project-logo-vertical.png">
|
||||||
|
|
||||||
# Next.js Enterprise Boilerplate </br> [![GitHub Actions Workflow Status][check-workflow-badge]][check-workflow-badge-link] [![GitHub License][github-license-badge]][github-license-badge-link] [![GitHub contributors][github-contributors-badge]][github-contributors-badge-link] [![Discord][discord-badge]][discord-badge-link] [![Blazity][made-by-blazity-badge]][made-by-blazity-badge-link]
|
# Next.js Enterprise Boilerplate </br> [![GitHub Actions Workflow Status][check-workflow-badge]][check-workflow-badge-link] [![GitHub License][github-license-badge]][github-license-badge-link] [![GitHub contributors][github-contributors-badge]][github-contributors-badge-link] [![Discord][discord-badge]][discord-badge-link] [![Blazity][made-by-blazity-badge]][made-by-blazity-badge-link]
|
||||||
|
|
||||||
Welcome to the _Next.js Enterprise Boilerplate_, an open-source template for enterprise projects! It's loaded with features that'll help you build a high-performance, maintainable, and enjoyable app. We've done all the heavy lifting for you, so sit back, relax, and get ready to conquer the world with your incredible app! 🌍
|
Welcome to the _Next.js Enterprise Boilerplate_, an open-source template for enterprise projects! It's loaded with features that'll help you build a high-performance, maintainable, and enjoyable app. We've done all the heavy lifting for you, so sit back, relax, and get ready to conquer the world with your incredible app! 🌍
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE] > **Blazity** is a group of Next.js/Headless experts. Contact us at [contact@blazity.com](https://blazity.com) if you’d like to talk about your project or just to have a chat with us
|
||||||
> **Blazity** is a group of Next.js/Headless experts. Contact us at [contact@blazity.com](https://blazity.com) if you’d like to talk about your project or just to have a chat with us
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -273,7 +272,6 @@ If you're looking for help or simply want to share your thoughts about the proje
|
||||||
</a>
|
</a>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
|
|
||||||
This project is licensed under the MIT License. For more information, see the [LICENSE](./LICENSE) file.
|
This project is licensed under the MIT License. For more information, see the [LICENSE](./LICENSE) file.
|
||||||
|
|
@ -314,7 +312,6 @@ This project is licensed under the MIT License. For more information, see the [L
|
||||||
[github-contributors-badge]: https://img.shields.io/github/contributors/blazity/next-enterprise?link=https%3A%2F%2Fgithub.com%2FBlazity%2Fnext-enterprise%2Fgraphs%2Fcontributors
|
[github-contributors-badge]: https://img.shields.io/github/contributors/blazity/next-enterprise?link=https%3A%2F%2Fgithub.com%2FBlazity%2Fnext-enterprise%2Fgraphs%2Fcontributors
|
||||||
[discord-badge]: https://img.shields.io/discord/1111676875782234175?color=7b8dcd&link=https%3A%2F%2Fblazity.com%2Fdiscord
|
[discord-badge]: https://img.shields.io/discord/1111676875782234175?color=7b8dcd&link=https%3A%2F%2Fblazity.com%2Fdiscord
|
||||||
[made-by-blazity-badge]: https://img.shields.io/badge/made_by-Blazity-blue?color=FF782B&link=https://blazity.com/
|
[made-by-blazity-badge]: https://img.shields.io/badge/made_by-Blazity-blue?color=FF782B&link=https://blazity.com/
|
||||||
|
|
||||||
[check-workflow-badge-link]: https://github.com/Blazity/next-enterprise/actions/workflows/check.yml
|
[check-workflow-badge-link]: https://github.com/Blazity/next-enterprise/actions/workflows/check.yml
|
||||||
[github-license-badge-link]: https://github.com/Blazity/next-enterprise/blob/main/LICENSE
|
[github-license-badge-link]: https://github.com/Blazity/next-enterprise/blob/main/LICENSE
|
||||||
[github-contributors-badge-link]: https://github.com/Blazity/next-enterprise/graphs/contributors
|
[github-contributors-badge-link]: https://github.com/Blazity/next-enterprise/graphs/contributors
|
||||||
|
|
|
||||||
28
app/account/controller/AuthController.tsx
Normal file
28
app/account/controller/AuthController.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { BASE_URL_AUTHENTICATION } from "@package/config/ApiPath"
|
||||||
|
import { FetchData } from "@package/config/FetchData"
|
||||||
|
|
||||||
|
async function auth(ae_user: string, ae_password: string): Promise<string> {
|
||||||
|
const options: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
// mode: 'cors',
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: ae_user,
|
||||||
|
password: ae_password,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await FetchData<{ token: string }>(BASE_URL_AUTHENTICATION, "login", options)
|
||||||
|
|
||||||
|
console.log(data)
|
||||||
|
if (data.correct) {
|
||||||
|
return data.object.token
|
||||||
|
} else {
|
||||||
|
console.error("Error en la autenticación:", data.message)
|
||||||
|
return "error en la autenticación"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { auth }
|
||||||
26
app/account/login/page.tsx
Normal file
26
app/account/login/page.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
"use client"
|
||||||
|
import LoginForm from "@organisms/LoginForm"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const LoginPage: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center bg-gradient-to-r from-blue-900 to-blue-700">
|
||||||
|
<div className="w-full max-w-md rounded-lg bg-white p-10 shadow-lg">
|
||||||
|
<h2 className="mb-8 text-center text-4xl font-bold text-blue-900">Iniciar Sesión</h2>
|
||||||
|
|
||||||
|
<LoginForm />
|
||||||
|
|
||||||
|
<div className="mt-4 text-center">
|
||||||
|
<button
|
||||||
|
onClick={() => alert("Recuperación de contraseña")} //TODO: Implement password recovery
|
||||||
|
className="text-sm text-blue-600 hover:underline"
|
||||||
|
>
|
||||||
|
¿Olvidaste tu contraseña?
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoginPage
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
return Response.json({ status: "ok" })
|
return new Response(JSON.stringify({ status: "ok" }), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
app/home/page.tsx
Normal file
14
app/home/page.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import CheckoutScreen from "@app/selfcheckout/CheckoutScreen"
|
||||||
|
import LoyaltyProgramScreen from "@app/selfcheckout/LoyaltyProgramScreen"
|
||||||
|
import PreCheckoutScreen from "@app/selfcheckout/PreCheckoutScreen"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const HomeAfterLogin: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-100 p-6">
|
||||||
|
<LoyaltyProgramScreen />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HomeAfterLogin
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import "styles/tailwind.css"
|
import "@package/styles/tailwind.css";
|
||||||
|
import Navbar from "@organisms/Navbar";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body>{children}</body>
|
<body>
|
||||||
|
<Navbar />
|
||||||
|
<main>{children}</main>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
121
app/page.tsx
121
app/page.tsx
|
|
@ -1,65 +1,68 @@
|
||||||
import { Metadata } from "next"
|
"use client"
|
||||||
import { Button } from "components/Button/Button"
|
import Grid from "@mui/material/Grid2"
|
||||||
import { LP_GRID_ITEMS } from "lp-items"
|
import Image from "next/image"
|
||||||
|
import { useRouter } from "next/navigation"
|
||||||
|
import Button from "@package/components/atoms/Button"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
const HomePage: React.FC = () => {
|
||||||
title: "Next.js Enterprise Boilerplate",
|
const router = useRouter()
|
||||||
twitter: {
|
|
||||||
card: "summary_large_image",
|
const handleLoginClick = () => {
|
||||||
},
|
router.push("/account/login")
|
||||||
openGraph: {
|
}
|
||||||
url: "https://next-enterprise.vercel.app/",
|
|
||||||
images: [
|
const handleFeaturesClick = () => {
|
||||||
{
|
router.push("/features")
|
||||||
width: 1200,
|
}
|
||||||
height: 630,
|
|
||||||
url: "https://raw.githubusercontent.com/Blazity/next-enterprise/main/.github/assets/project-logo.png",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Web() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Grid
|
||||||
<section className="bg-white dark:bg-gray-900">
|
container
|
||||||
<div className="mx-auto grid max-w-screen-xl px-4 py-8 text-center lg:py-16">
|
className="min-h-screen"
|
||||||
<div className="mx-auto place-self-center">
|
alignItems="center"
|
||||||
<h1 className="mb-4 max-w-2xl text-4xl font-extrabold leading-none tracking-tight dark:text-white md:text-5xl xl:text-6xl">
|
justifyContent="center"
|
||||||
Next.js Enterprise Boilerplate
|
sx={{
|
||||||
</h1>
|
background: "linear-gradient(to right, black, #2c3e50, #0064dc)",
|
||||||
<p className="mb-6 max-w-2xl font-light text-gray-500 dark:text-gray-400 md:text-lg lg:mb-8 lg:text-xl">
|
alignItems: "center",
|
||||||
Jumpstart your enterprise project with our feature-packed, high-performance Next.js boilerplate!
|
justifyContent: "center",
|
||||||
Experience rapid UI development, AI-powered code reviews, and an extensive suite of tools for a smooth and
|
}}
|
||||||
enjoyable development process.
|
>
|
||||||
</p>
|
<Grid size={{ xs: 12, md: 6 }} display="flex" justifyContent={{ xs: "center", md: "flex-end" }}>
|
||||||
<Button href="https://github.com/Blazity/next-enterprise" className="mr-3">
|
<Image
|
||||||
Get started
|
src="/img/selfcheckout.jpg"
|
||||||
</Button>
|
alt="Checkout"
|
||||||
|
width={500}
|
||||||
|
height={400}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
className="rounded-lg shadow-lg"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 12, md: 6 }} textAlign={{ xs: "center", md: "left" }} padding={{ md: "0 24px" }}>
|
||||||
|
<h1 className="mb-4 text-5xl font-bold text-white md:text-6xl">SELF CHECKOUT</h1>
|
||||||
|
|
||||||
|
<p className="mb-6 text-xl text-gray-200 md:text-2xl">Mejorando la experiencia en tienda</p>
|
||||||
|
|
||||||
|
<Grid container justifyContent={{ xs: "center", md: "flex-start" }} spacing={2}>
|
||||||
|
<Grid size={{ xs: 6, md: 6 }}>
|
||||||
<Button
|
<Button
|
||||||
href="https://vercel.com/new/git/external?repository-url=https://github.com/Blazity/next-enterprise"
|
label="Iniciar Sesión"
|
||||||
intent="secondary"
|
onClick={handleLoginClick}
|
||||||
>
|
className="rounded-lg bg-blue-600 px-6 py-3 text-lg text-white transition hover:bg-blue-700"
|
||||||
Deploy Now
|
/>
|
||||||
</Button>
|
</Grid>
|
||||||
</div>
|
<Grid size={{ xs: 6, md: 6 }}>
|
||||||
</div>
|
<Button
|
||||||
</section>
|
label="Ver Funcionalidades"
|
||||||
<section className="bg-white dark:bg-gray-900">
|
onClick={handleFeaturesClick}
|
||||||
<div className="mx-auto max-w-screen-xl px-4 py-8 sm:py-16 lg:px-6">
|
className="rounded-lg bg-gray-200 px-6 py-3 text-lg text-blue-600 transition hover:bg-gray-300"
|
||||||
<div className="justify-center space-y-8 md:grid md:grid-cols-2 md:gap-12 md:space-y-0 lg:grid-cols-3">
|
/>
|
||||||
{LP_GRID_ITEMS.map((singleItem) => (
|
</Grid>
|
||||||
<div key={singleItem.title} className="flex flex-col items-center justify-center text-center">
|
</Grid>
|
||||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-full bg-primary-100 p-1.5 text-blue-700 dark:bg-primary-900 lg:h-12 lg:w-12">
|
</Grid>
|
||||||
{singleItem.icon}
|
</Grid>
|
||||||
</div>
|
|
||||||
<h3 className="mb-2 text-xl font-bold dark:text-white">{singleItem.title}</h3>
|
|
||||||
<p className="text-gray-500 dark:text-gray-400">{singleItem.description}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default HomePage
|
||||||
|
|
|
||||||
34
app/selfcheckout/CheckoutScreen.tsx
Normal file
34
app/selfcheckout/CheckoutScreen.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Container } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2" // Usando Grid2
|
||||||
|
import ButtonPanel from "@organisms/ButtonPanel"
|
||||||
|
import Header from "@organisms/Header"
|
||||||
|
import MainPanel from "@organisms/MainPanel"
|
||||||
|
import ProductList from "@organisms/ProductList"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const CheckoutScreen: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Container maxWidth="xl" sx={{ minHeight: "100vh", bgcolor: "background.default", padding: 0 }}>
|
||||||
|
<Header sx={{ minHeight: "64px", marginBottom: 1 }} />
|
||||||
|
|
||||||
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
|
<Grid container spacing={2} alignItems="stretch" sx={{ height: "calc(100vh - 64px)" }}>
|
||||||
|
<Grid size={{ xs: 12, md: 4 }} sx={{ height: "100%" }}>
|
||||||
|
<ProductList />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 12, md: 4 }} sx={{ height: "100%" }}>
|
||||||
|
<ButtonPanel />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 12, md: 4 }} sx={{ height: "100%" }}>
|
||||||
|
<MainPanel />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutScreen
|
||||||
99
app/selfcheckout/LoyaltyProgramScreen.tsx
Normal file
99
app/selfcheckout/LoyaltyProgramScreen.tsx
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
"use client"
|
||||||
|
import CheckoutScreen from "@app/selfcheckout/CheckoutScreen"
|
||||||
|
import AskForAffiliation from "@layouts/AskForAffiliation"
|
||||||
|
import IdentityDocumentNumber from "@layouts/IdentityDocumentNumber"
|
||||||
|
import TypeIdentityDocument from "@layouts/TypeIdentityDocument"
|
||||||
|
import { Box, Card, CardContent, Container } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import Header from "@organisms/Header"
|
||||||
|
import { getDocumentsByCountry } from "@package/utils/getDocumentsByCountry"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
const LoyaltyProgramScreen: React.FC = () => {
|
||||||
|
const [isAffiliated, setIsAffiliated] = useState<boolean | null>(null)
|
||||||
|
const [documentType, setDocumentType] = useState<string | null>(null)
|
||||||
|
const [documentNumber, setDocumentNumber] = useState<string | null>(null)
|
||||||
|
const [goToCheckout, setGoToCheckout] = useState<boolean>(false)
|
||||||
|
const [countryDocumentTypes, setCountryDocumentTypes] = useState<string[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const documents = getDocumentsByCountry()
|
||||||
|
setCountryDocumentTypes(documents)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleAffiliationSelect = (isAffiliated: boolean) => {
|
||||||
|
setIsAffiliated(isAffiliated)
|
||||||
|
if (!isAffiliated) {
|
||||||
|
setDocumentType("13")
|
||||||
|
setDocumentNumber("222222222222")
|
||||||
|
setGoToCheckout(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDocumentSelect = (selectedDocumentType: string) => {
|
||||||
|
setDocumentType(selectedDocumentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDocumentNumberSubmit = (enteredDocumentNumber: string) => {
|
||||||
|
setDocumentNumber(enteredDocumentNumber)
|
||||||
|
setGoToCheckout(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (goToCheckout) {
|
||||||
|
return <CheckoutScreen />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
maxWidth={false}
|
||||||
|
sx={{
|
||||||
|
height: "100hv",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Card sx={{ width: "100%", p: 2 }}>
|
||||||
|
<Header sx={{ minHeight: "32px", marginBottom: 1 }} />
|
||||||
|
|
||||||
|
<CardContent sx={{ padding: "4px", height: "100%" }}>
|
||||||
|
<Grid container spacing={2} sx={{ height: "100%" }} alignItems="center">
|
||||||
|
<Grid size={{ xs: 12, md: 6 }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100%",
|
||||||
|
bgcolor: "#f5f5f5",
|
||||||
|
p: 5,
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component="img"
|
||||||
|
src="/img/logo.png"
|
||||||
|
alt="Rhiscom Logo"
|
||||||
|
sx={{ width: "600px", height: "auto", mb: 15 }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 12, md: 6 }}>
|
||||||
|
{isAffiliated === null && <AskForAffiliation onAffiliationSelect={handleAffiliationSelect} />}
|
||||||
|
{isAffiliated && !documentType && (
|
||||||
|
<TypeIdentityDocument typesDocument={countryDocumentTypes} onDocumentSelect={handleDocumentSelect} />
|
||||||
|
)}
|
||||||
|
{isAffiliated && documentType && (
|
||||||
|
<IdentityDocumentNumber documentType={documentType} onSubmit={handleDocumentNumberSubmit} />
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoyaltyProgramScreen
|
||||||
36
app/selfcheckout/PreCheckoutScreen.tsx
Normal file
36
app/selfcheckout/PreCheckoutScreen.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
"use client"
|
||||||
|
import Title from "@atoms/Title"
|
||||||
|
import { Tooltip } from "@atoms/Tooltip"
|
||||||
|
import { Box, Button, Container } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const PreCheckoutScreen: React.FC = () => {
|
||||||
|
const handleStartCheckout = () => {
|
||||||
|
console.log("Comenzar checkout")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container maxWidth="md" sx={{ textAlign: "center", marginTop: "20vh" }}>
|
||||||
|
<Box sx={{ backgroundColor: "#f1f1f1", padding: "40px", borderRadius: "8px", boxShadow: 3 }}>
|
||||||
|
<Title text="Esta caja está" size="h4" />
|
||||||
|
<Title text="Abierta" size="h2" />
|
||||||
|
|
||||||
|
<Tooltip explainer="Escanee un producto o pulse el botón para comenzar" withArrow side="top">
|
||||||
|
<Title text="Escanee un producto o pulse aquí para comenzar" size="h6" />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="success"
|
||||||
|
size="large"
|
||||||
|
sx={{ marginTop: "40px" }}
|
||||||
|
onClick={handleStartCheckout}
|
||||||
|
>
|
||||||
|
Comenzar
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PreCheckoutScreen
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import type { Meta, StoryObj } from "@storybook/react"
|
|
||||||
import { Button } from "./Button"
|
|
||||||
|
|
||||||
const meta: Meta<typeof Button> = {
|
|
||||||
title: "Button",
|
|
||||||
component: Button,
|
|
||||||
args: {
|
|
||||||
intent: "primary",
|
|
||||||
underline: false,
|
|
||||||
children: "Button",
|
|
||||||
size: "lg",
|
|
||||||
},
|
|
||||||
argTypes: {
|
|
||||||
intent: {
|
|
||||||
options: ["primary", "secondary"],
|
|
||||||
control: { type: "select" },
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
options: ["sm", "lg"],
|
|
||||||
control: { type: "select" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof Button>
|
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
render: (args) => <Button {...args} />,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default meta
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
|
|
||||||
import { twMerge } from "tailwind-merge"
|
|
||||||
|
|
||||||
const button = cva(
|
|
||||||
[
|
|
||||||
"justify-center",
|
|
||||||
"inline-flex",
|
|
||||||
"items-center",
|
|
||||||
"rounded-xl",
|
|
||||||
"text-center",
|
|
||||||
"border",
|
|
||||||
"border-blue-400",
|
|
||||||
"transition-colors",
|
|
||||||
"delay-50",
|
|
||||||
],
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
intent: {
|
|
||||||
primary: ["bg-blue-400", "text-white", "hover:enabled:bg-blue-700"],
|
|
||||||
secondary: ["bg-transparent", "text-blue-400", "hover:enabled:bg-blue-400", "hover:enabled:text-white"],
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
sm: ["min-w-20", "h-full", "min-h-10", "text-sm", "py-1.5", "px-4"],
|
|
||||||
lg: ["min-w-32", "h-full", "min-h-12", "text-lg", "py-2.5", "px-6"],
|
|
||||||
},
|
|
||||||
underline: { true: ["underline"], false: [] },
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
intent: "primary",
|
|
||||||
size: "lg",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLAnchorElement>, VariantProps<typeof button> {
|
|
||||||
underline?: boolean
|
|
||||||
href: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Button({ className, intent, size, underline, ...props }: ButtonProps) {
|
|
||||||
return (
|
|
||||||
<a className={twMerge(button({ intent, size, className, underline }))} {...props}>
|
|
||||||
{props.children}
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
5
env.mjs
5
env.mjs
|
|
@ -8,8 +8,11 @@ export const env = createEnv({
|
||||||
.optional()
|
.optional()
|
||||||
.transform((value) => value === "true"),
|
.transform((value) => value === "true"),
|
||||||
},
|
},
|
||||||
client: {},
|
client: {
|
||||||
|
NEXT_PUBLIC_API_URL: z.string().url(),
|
||||||
|
},
|
||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
ANALYZE: process.env.ANALYZE,
|
ANALYZE: process.env.ANALYZE,
|
||||||
|
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
---
|
---
|
||||||
convention:
|
convention:
|
||||||
commitTypes:
|
commitTypes:
|
||||||
- feat
|
- feat
|
||||||
- fix
|
- fix
|
||||||
- perf
|
- perf
|
||||||
- refactor
|
- refactor
|
||||||
- style
|
- style
|
||||||
- test
|
- test
|
||||||
- build
|
- build
|
||||||
- ops
|
- ops
|
||||||
- docs
|
- docs
|
||||||
- chore
|
- chore
|
||||||
- merge
|
- merge
|
||||||
- revert
|
- revert
|
||||||
commitScopes: []
|
commitScopes: []
|
||||||
releaseTagGlobPattern: v[0-9]*.[0-9]*.[0-9]*
|
releaseTagGlobPattern: v[0-9]*.[0-9]*.[0-9]*
|
||||||
changelog:
|
changelog:
|
||||||
commitTypes:
|
commitTypes:
|
||||||
- feat
|
- feat
|
||||||
- fix
|
- fix
|
||||||
- perf
|
- perf
|
||||||
- merge
|
- merge
|
||||||
includeInvalidCommits: true
|
includeInvalidCommits: true
|
||||||
commitIgnoreRegexPattern: "^WIP "
|
commitIgnoreRegexPattern: "^WIP "
|
||||||
headlines:
|
headlines:
|
||||||
|
|
|
||||||
170
graph.svg
170
graph.svg
|
|
@ -1,85 +1,85 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<!-- Generated by graphviz version 8.0.2 (20230410.1723)
|
<!-- Generated by graphviz version 8.0.2 (20230410.1723)
|
||||||
-->
|
-->
|
||||||
<!-- Title: G Pages: 1 -->
|
<!-- Title: G Pages: 1 -->
|
||||||
<svg width="677pt" height="230pt"
|
<svg width="677pt" height="230pt"
|
||||||
viewBox="0.00 0.00 677.20 230.20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
viewBox="0.00 0.00 677.20 230.20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(21.6 208.6)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(21.6 208.6)">
|
||||||
<title>G</title>
|
<title>G</title>
|
||||||
<polygon fill="#111111" stroke="none" points="-21.6,21.6 -21.6,-208.6 655.6,-208.6 655.6,21.6 -21.6,21.6"/>
|
<polygon fill="#111111" stroke="none" points="-21.6,21.6 -21.6,-208.6 655.6,-208.6 655.6,21.6 -21.6,21.6"/>
|
||||||
<!-- components/Button/Button.stories.tsx -->
|
<!-- components/Button/Button.stories.tsx -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>components/Button/Button.stories.tsx</title>
|
<title>components/Button/Button.stories.tsx</title>
|
||||||
<path fill="none" stroke="#c6c5fe" d="M233.33,-64C233.33,-64 7.67,-64 7.67,-64 3.83,-64 0,-60.17 0,-56.33 0,-56.33 0,-48.67 0,-48.67 0,-44.83 3.83,-41 7.67,-41 7.67,-41 233.33,-41 233.33,-41 237.17,-41 241,-44.83 241,-48.67 241,-48.67 241,-56.33 241,-56.33 241,-60.17 237.17,-64 233.33,-64"/>
|
<path fill="none" stroke="#c6c5fe" d="M233.33,-64C233.33,-64 7.67,-64 7.67,-64 3.83,-64 0,-60.17 0,-56.33 0,-56.33 0,-48.67 0,-48.67 0,-44.83 3.83,-41 7.67,-41 7.67,-41 233.33,-41 233.33,-41 237.17,-41 241,-44.83 241,-48.67 241,-48.67 241,-56.33 241,-56.33 241,-60.17 237.17,-64 233.33,-64"/>
|
||||||
<text text-anchor="middle" x="120.5" y="-48.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">components/Button/Button.stories.tsx</text>
|
<text text-anchor="middle" x="120.5" y="-48.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">components/Button/Button.stories.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- components/Button/Button.tsx -->
|
<!-- components/Button/Button.tsx -->
|
||||||
<g id="node2" class="node">
|
<g id="node2" class="node">
|
||||||
<title>components/Button/Button.tsx</title>
|
<title>components/Button/Button.tsx</title>
|
||||||
<path fill="none" stroke="#cfffac" d="M466.33,-43C466.33,-43 284.67,-43 284.67,-43 280.83,-43 277,-39.17 277,-35.33 277,-35.33 277,-27.67 277,-27.67 277,-23.83 280.83,-20 284.67,-20 284.67,-20 466.33,-20 466.33,-20 470.17,-20 474,-23.83 474,-27.67 474,-27.67 474,-35.33 474,-35.33 474,-39.17 470.17,-43 466.33,-43"/>
|
<path fill="none" stroke="#cfffac" d="M466.33,-43C466.33,-43 284.67,-43 284.67,-43 280.83,-43 277,-39.17 277,-35.33 277,-35.33 277,-27.67 277,-27.67 277,-23.83 280.83,-20 284.67,-20 284.67,-20 466.33,-20 466.33,-20 470.17,-20 474,-23.83 474,-27.67 474,-27.67 474,-35.33 474,-35.33 474,-39.17 470.17,-43 466.33,-43"/>
|
||||||
<text text-anchor="middle" x="375.5" y="-27.8" font-family="Arial" font-size="14.00" fill="#cfffac">components/Button/Button.tsx</text>
|
<text text-anchor="middle" x="375.5" y="-27.8" font-family="Arial" font-size="14.00" fill="#cfffac">components/Button/Button.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- components/Button/Button.stories.tsx->components/Button/Button.tsx -->
|
<!-- components/Button/Button.stories.tsx->components/Button/Button.tsx -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge1" class="edge">
|
||||||
<title>components/Button/Button.stories.tsx->components/Button/Button.tsx</title>
|
<title>components/Button/Button.stories.tsx->components/Button/Button.tsx</title>
|
||||||
<path fill="none" stroke="#757575" d="M241.33,-42.55C249.59,-41.87 257.89,-41.18 266.08,-40.5"/>
|
<path fill="none" stroke="#757575" d="M241.33,-42.55C249.59,-41.87 257.89,-41.18 266.08,-40.5"/>
|
||||||
<polygon fill="#757575" stroke="#757575" points="266.1,-43.93 275.78,-39.61 265.53,-36.95 266.1,-43.93"/>
|
<polygon fill="#757575" stroke="#757575" points="266.1,-43.93 275.78,-39.61 265.53,-36.95 266.1,-43.93"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- components/Tooltip/Tooltip.tsx -->
|
<!-- components/Tooltip/Tooltip.tsx -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>components/Tooltip/Tooltip.tsx</title>
|
<title>components/Tooltip/Tooltip.tsx</title>
|
||||||
<path fill="none" stroke="#cfffac" d="M211.33,-105C211.33,-105 29.67,-105 29.67,-105 25.83,-105 22,-101.17 22,-97.33 22,-97.33 22,-89.67 22,-89.67 22,-85.83 25.83,-82 29.67,-82 29.67,-82 211.33,-82 211.33,-82 215.17,-82 219,-85.83 219,-89.67 219,-89.67 219,-97.33 219,-97.33 219,-101.17 215.17,-105 211.33,-105"/>
|
<path fill="none" stroke="#cfffac" d="M211.33,-105C211.33,-105 29.67,-105 29.67,-105 25.83,-105 22,-101.17 22,-97.33 22,-97.33 22,-89.67 22,-89.67 22,-85.83 25.83,-82 29.67,-82 29.67,-82 211.33,-82 211.33,-82 215.17,-82 219,-85.83 219,-89.67 219,-89.67 219,-97.33 219,-97.33 219,-101.17 215.17,-105 211.33,-105"/>
|
||||||
<text text-anchor="middle" x="120.5" y="-89.8" font-family="Arial" font-size="14.00" fill="#cfffac">components/Tooltip/Tooltip.tsx</text>
|
<text text-anchor="middle" x="120.5" y="-89.8" font-family="Arial" font-size="14.00" fill="#cfffac">components/Tooltip/Tooltip.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/_app.test.tsx -->
|
<!-- pages/_app.test.tsx -->
|
||||||
<g id="node4" class="node">
|
<g id="node4" class="node">
|
||||||
<title>pages/_app.test.tsx</title>
|
<title>pages/_app.test.tsx</title>
|
||||||
<path fill="none" stroke="#c6c5fe" d="M179.83,-146C179.83,-146 61.17,-146 61.17,-146 57.33,-146 53.5,-142.17 53.5,-138.33 53.5,-138.33 53.5,-130.67 53.5,-130.67 53.5,-126.83 57.33,-123 61.17,-123 61.17,-123 179.83,-123 179.83,-123 183.67,-123 187.5,-126.83 187.5,-130.67 187.5,-130.67 187.5,-138.33 187.5,-138.33 187.5,-142.17 183.67,-146 179.83,-146"/>
|
<path fill="none" stroke="#c6c5fe" d="M179.83,-146C179.83,-146 61.17,-146 61.17,-146 57.33,-146 53.5,-142.17 53.5,-138.33 53.5,-138.33 53.5,-130.67 53.5,-130.67 53.5,-126.83 57.33,-123 61.17,-123 61.17,-123 179.83,-123 179.83,-123 183.67,-123 187.5,-126.83 187.5,-130.67 187.5,-130.67 187.5,-138.33 187.5,-138.33 187.5,-142.17 183.67,-146 179.83,-146"/>
|
||||||
<text text-anchor="middle" x="120.5" y="-130.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/_app.test.tsx</text>
|
<text text-anchor="middle" x="120.5" y="-130.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/_app.test.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/_app.tsx -->
|
<!-- pages/_app.tsx -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>pages/_app.tsx</title>
|
<title>pages/_app.tsx</title>
|
||||||
<path fill="none" stroke="#c6c5fe" d="M421.83,-146C421.83,-146 329.17,-146 329.17,-146 325.33,-146 321.5,-142.17 321.5,-138.33 321.5,-138.33 321.5,-130.67 321.5,-130.67 321.5,-126.83 325.33,-123 329.17,-123 329.17,-123 421.83,-123 421.83,-123 425.67,-123 429.5,-126.83 429.5,-130.67 429.5,-130.67 429.5,-138.33 429.5,-138.33 429.5,-142.17 425.67,-146 421.83,-146"/>
|
<path fill="none" stroke="#c6c5fe" d="M421.83,-146C421.83,-146 329.17,-146 329.17,-146 325.33,-146 321.5,-142.17 321.5,-138.33 321.5,-138.33 321.5,-130.67 321.5,-130.67 321.5,-126.83 325.33,-123 329.17,-123 329.17,-123 421.83,-123 421.83,-123 425.67,-123 429.5,-126.83 429.5,-130.67 429.5,-130.67 429.5,-138.33 429.5,-138.33 429.5,-142.17 425.67,-146 421.83,-146"/>
|
||||||
<text text-anchor="middle" x="375.5" y="-130.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/_app.tsx</text>
|
<text text-anchor="middle" x="375.5" y="-130.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/_app.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/_app.test.tsx->pages/_app.tsx -->
|
<!-- pages/_app.test.tsx->pages/_app.tsx -->
|
||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>pages/_app.test.tsx->pages/_app.tsx</title>
|
<title>pages/_app.test.tsx->pages/_app.tsx</title>
|
||||||
<path fill="none" stroke="#757575" d="M187.97,-134.5C225.82,-134.5 272.99,-134.5 310.43,-134.5"/>
|
<path fill="none" stroke="#757575" d="M187.97,-134.5C225.82,-134.5 272.99,-134.5 310.43,-134.5"/>
|
||||||
<polygon fill="#757575" stroke="#757575" points="310.21,-138 320.21,-134.5 310.21,-131 310.21,-138"/>
|
<polygon fill="#757575" stroke="#757575" points="310.21,-138 320.21,-134.5 310.21,-131 310.21,-138"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- styles/tailwind.css -->
|
<!-- styles/tailwind.css -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>styles/tailwind.css</title>
|
<title>styles/tailwind.css</title>
|
||||||
<path fill="none" stroke="#cfffac" d="M626.33,-146C626.33,-146 517.67,-146 517.67,-146 513.83,-146 510,-142.17 510,-138.33 510,-138.33 510,-130.67 510,-130.67 510,-126.83 513.83,-123 517.67,-123 517.67,-123 626.33,-123 626.33,-123 630.17,-123 634,-126.83 634,-130.67 634,-130.67 634,-138.33 634,-138.33 634,-142.17 630.17,-146 626.33,-146"/>
|
<path fill="none" stroke="#cfffac" d="M626.33,-146C626.33,-146 517.67,-146 517.67,-146 513.83,-146 510,-142.17 510,-138.33 510,-138.33 510,-130.67 510,-130.67 510,-126.83 513.83,-123 517.67,-123 517.67,-123 626.33,-123 626.33,-123 630.17,-123 634,-126.83 634,-130.67 634,-130.67 634,-138.33 634,-138.33 634,-142.17 630.17,-146 626.33,-146"/>
|
||||||
<text text-anchor="middle" x="572" y="-130.8" font-family="Arial" font-size="14.00" fill="#cfffac">styles/tailwind.css</text>
|
<text text-anchor="middle" x="572" y="-130.8" font-family="Arial" font-size="14.00" fill="#cfffac">styles/tailwind.css</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/_app.tsx->styles/tailwind.css -->
|
<!-- pages/_app.tsx->styles/tailwind.css -->
|
||||||
<g id="edge3" class="edge">
|
<g id="edge3" class="edge">
|
||||||
<title>pages/_app.tsx->styles/tailwind.css</title>
|
<title>pages/_app.tsx->styles/tailwind.css</title>
|
||||||
<path fill="none" stroke="#757575" d="M429.91,-134.5C451.26,-134.5 476.19,-134.5 499.1,-134.5"/>
|
<path fill="none" stroke="#757575" d="M429.91,-134.5C451.26,-134.5 476.19,-134.5 499.1,-134.5"/>
|
||||||
<polygon fill="#757575" stroke="#757575" points="498.81,-138 508.81,-134.5 498.81,-131 498.81,-138"/>
|
<polygon fill="#757575" stroke="#757575" points="498.81,-138 508.81,-134.5 498.81,-131 498.81,-138"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/api/health.ts -->
|
<!-- pages/api/health.ts -->
|
||||||
<g id="node7" class="node">
|
<g id="node7" class="node">
|
||||||
<title>pages/api/health.ts</title>
|
<title>pages/api/health.ts</title>
|
||||||
<path fill="none" stroke="#cfffac" d="M177.83,-187C177.83,-187 63.17,-187 63.17,-187 59.33,-187 55.5,-183.17 55.5,-179.33 55.5,-179.33 55.5,-171.67 55.5,-171.67 55.5,-167.83 59.33,-164 63.17,-164 63.17,-164 177.83,-164 177.83,-164 181.67,-164 185.5,-167.83 185.5,-171.67 185.5,-171.67 185.5,-179.33 185.5,-179.33 185.5,-183.17 181.67,-187 177.83,-187"/>
|
<path fill="none" stroke="#cfffac" d="M177.83,-187C177.83,-187 63.17,-187 63.17,-187 59.33,-187 55.5,-183.17 55.5,-179.33 55.5,-179.33 55.5,-171.67 55.5,-171.67 55.5,-167.83 59.33,-164 63.17,-164 63.17,-164 177.83,-164 177.83,-164 181.67,-164 185.5,-167.83 185.5,-171.67 185.5,-171.67 185.5,-179.33 185.5,-179.33 185.5,-183.17 181.67,-187 177.83,-187"/>
|
||||||
<text text-anchor="middle" x="120.5" y="-171.8" font-family="Arial" font-size="14.00" fill="#cfffac">pages/api/health.ts</text>
|
<text text-anchor="middle" x="120.5" y="-171.8" font-family="Arial" font-size="14.00" fill="#cfffac">pages/api/health.ts</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/index.tsx -->
|
<!-- pages/index.tsx -->
|
||||||
<g id="node8" class="node">
|
<g id="node8" class="node">
|
||||||
<title>pages/index.tsx</title>
|
<title>pages/index.tsx</title>
|
||||||
<path fill="none" stroke="#c6c5fe" d="M167.83,-23C167.83,-23 73.17,-23 73.17,-23 69.33,-23 65.5,-19.17 65.5,-15.33 65.5,-15.33 65.5,-7.67 65.5,-7.67 65.5,-3.83 69.33,0 73.17,0 73.17,0 167.83,0 167.83,0 171.67,0 175.5,-3.83 175.5,-7.67 175.5,-7.67 175.5,-15.33 175.5,-15.33 175.5,-19.17 171.67,-23 167.83,-23"/>
|
<path fill="none" stroke="#c6c5fe" d="M167.83,-23C167.83,-23 73.17,-23 73.17,-23 69.33,-23 65.5,-19.17 65.5,-15.33 65.5,-15.33 65.5,-7.67 65.5,-7.67 65.5,-3.83 69.33,0 73.17,0 73.17,0 167.83,0 167.83,0 171.67,0 175.5,-3.83 175.5,-7.67 175.5,-7.67 175.5,-15.33 175.5,-15.33 175.5,-19.17 171.67,-23 167.83,-23"/>
|
||||||
<text text-anchor="middle" x="120.5" y="-7.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/index.tsx</text>
|
<text text-anchor="middle" x="120.5" y="-7.8" font-family="Arial" font-size="14.00" fill="#c6c5fe">pages/index.tsx</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- pages/index.tsx->components/Button/Button.tsx -->
|
<!-- pages/index.tsx->components/Button/Button.tsx -->
|
||||||
<g id="edge4" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>pages/index.tsx->components/Button/Button.tsx</title>
|
<title>pages/index.tsx->components/Button/Button.tsx</title>
|
||||||
<path fill="none" stroke="#757575" d="M175.77,-15.79C202.08,-17.87 234.64,-20.44 265.75,-22.9"/>
|
<path fill="none" stroke="#757575" d="M175.77,-15.79C202.08,-17.87 234.64,-20.44 265.75,-22.9"/>
|
||||||
<polygon fill="#757575" stroke="#757575" points="265.43,-26.47 275.67,-23.77 265.98,-19.49 265.43,-26.47"/>
|
<polygon fill="#757575" stroke="#757575" points="265.43,-26.47 275.67,-23.77 265.98,-19.49 265.43,-26.47"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.5 KiB |
|
|
@ -1,5 +1,42 @@
|
||||||
|
import { context, diag, DiagConsoleLogger, DiagLogLevel, propagation, trace } from "@opentelemetry/api"
|
||||||
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto"
|
||||||
|
import { Resource } from "@opentelemetry/resources"
|
||||||
|
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"
|
||||||
|
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"
|
||||||
import { registerOTel } from "@vercel/otel"
|
import { registerOTel } from "@vercel/otel"
|
||||||
|
|
||||||
export function register() {
|
// Configuración del logger de diagnóstico
|
||||||
registerOTel("next-app")
|
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)
|
||||||
|
|
||||||
|
// Verificación de registro previo de OpenTelemetry
|
||||||
|
function isAlreadyRegistered() {
|
||||||
|
return trace.getTracerProvider() || context.active() || propagation.setGlobalPropagator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicialización de OpenTelemetry
|
||||||
|
function initializeOpenTelemetry() {
|
||||||
|
const resource = new Resource({
|
||||||
|
"service.name": "next-app", // Cambia el nombre del servicio según tu proyecto
|
||||||
|
})
|
||||||
|
|
||||||
|
const provider = new NodeTracerProvider({
|
||||||
|
resource,
|
||||||
|
})
|
||||||
|
|
||||||
|
const traceExporter = new OTLPTraceExporter({
|
||||||
|
url: "http://localhost:4318/v1/traces", // Asegúrate de que el servicio OTLP esté corriendo
|
||||||
|
})
|
||||||
|
|
||||||
|
provider.addSpanProcessor(new BatchSpanProcessor(traceExporter))
|
||||||
|
provider.register()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registrar OpenTelemetry si no está registrado
|
||||||
|
if (!isAlreadyRegistered()) {
|
||||||
|
initializeOpenTelemetry()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registrar la configuración de OpenTelemetry
|
||||||
|
export function register() {
|
||||||
|
registerOTel("next-app") // Mismo nombre de servicio
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
lp-items.tsx
42
lp-items.tsx
|
|
@ -9,7 +9,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -29,7 +29,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -49,7 +49,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
|
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
@ -65,7 +65,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -85,7 +85,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -105,7 +105,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -125,7 +125,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -145,7 +145,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -165,7 +165,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -185,7 +185,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -205,7 +205,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -226,7 +226,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -246,7 +246,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -266,7 +266,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -286,7 +286,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -306,7 +306,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -326,7 +326,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -346,7 +346,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 6a7.5 7.5 0 107.5 7.5h-7.5V6z" />
|
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 6a7.5 7.5 0 107.5 7.5h-7.5V6z" />
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 10.5H21A7.5 7.5 0 0013.5 3v7.5z" />
|
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 10.5H21A7.5 7.5 0 0013.5 3v7.5z" />
|
||||||
|
|
@ -363,7 +363,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -383,7 +383,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
@ -403,7 +403,7 @@ export const LP_GRID_ITEMS = [
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="h-6 w-6"
|
className="size-6"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
|
import { trace } from "@opentelemetry/api"
|
||||||
import { NextResponse } from "next/server"
|
import { NextResponse } from "next/server"
|
||||||
import type { NextRequest } from "next/server"
|
import type { NextRequest } from "next/server"
|
||||||
|
|
||||||
export function middleware(request: NextRequest) {
|
export function middleware(request: NextRequest) {
|
||||||
|
// Iniciar una nueva traza para el middleware
|
||||||
|
const tracer = trace.getTracer("nextjs-middleware")
|
||||||
|
const span = tracer.startSpan("middleware-span")
|
||||||
|
|
||||||
// TODO: Feel free to remove this block
|
// TODO: Feel free to remove this block
|
||||||
if (request.headers?.get("host")?.includes("next-enterprise.vercel.app")) {
|
if (request.headers?.get("host")?.includes("next-enterprise.vercel.app")) {
|
||||||
|
span.setAttribute("redirect", true)
|
||||||
|
span.end()
|
||||||
return NextResponse.redirect("https://blazity.com/open-source/nextjs-enterprise-boilerplate", { status: 301 })
|
return NextResponse.redirect("https://blazity.com/open-source/nextjs-enterprise-boilerplate", { status: 301 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finalizar la traza
|
||||||
|
span.end()
|
||||||
|
return NextResponse.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
||||||
/*
|
|
||||||
* Match all request paths except for the ones starting with:
|
|
||||||
* - api (API routes)
|
|
||||||
* - _next/static (static files)
|
|
||||||
* - _next/image (image optimization files)
|
|
||||||
* - favicon.ico (favicon file)
|
|
||||||
*/
|
|
||||||
"/((?!api|_next/static|_next/image|favicon.ico).*)",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
|
|
@ -2,4 +2,4 @@
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,11 @@ import { env } from "./env.mjs"
|
||||||
*/
|
*/
|
||||||
const config = withPlugins([[withBundleAnalyzer({ enabled: env.ANALYZE })]], {
|
const config = withPlugins([[withBundleAnalyzer({ enabled: env.ANALYZE })]], {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
experimental: { instrumentationHook: true },
|
experimental: { instrumentationHook: false },
|
||||||
|
env: {
|
||||||
|
REACT_APP_API_URL: process.env.REACT_APP_API_URL, // Para que esté disponible en el cliente
|
||||||
|
},
|
||||||
|
|
||||||
rewrites() {
|
rewrites() {
|
||||||
return [
|
return [
|
||||||
{ source: "/healthz", destination: "/api/health" },
|
{ source: "/healthz", destination: "/api/health" },
|
||||||
|
|
|
||||||
31
package.json
31
package.json
|
|
@ -23,7 +23,14 @@
|
||||||
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|.storybook/|.eslintrc.js' --image graph.svg"
|
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|.storybook/|.eslintrc.js' --image graph.svg"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.13.3",
|
||||||
|
"@emotion/styled": "^11.13.0",
|
||||||
|
"@mui/icons-material": "^6.1.0",
|
||||||
|
"@mui/material": "^6.1.0",
|
||||||
|
"@mui/system": "^6.1.0",
|
||||||
"@next/bundle-analyzer": "^14.0.3",
|
"@next/bundle-analyzer": "^14.0.3",
|
||||||
|
"@opentelemetry/exporter-trace-otlp-http": "^0.53.0",
|
||||||
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.53.0",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
|
|
@ -39,6 +46,7 @@
|
||||||
"@radix-ui/react-tabs": "^1.0.4",
|
"@radix-ui/react-tabs": "^1.0.4",
|
||||||
"@radix-ui/react-toggle-group": "^1.0.4",
|
"@radix-ui/react-toggle-group": "^1.0.4",
|
||||||
"@radix-ui/react-tooltip": "^1.0.7",
|
"@radix-ui/react-tooltip": "^1.0.7",
|
||||||
|
"@radix-ui/themes": "^3.1.3",
|
||||||
"@semantic-release/changelog": "^6.0.3",
|
"@semantic-release/changelog": "^6.0.3",
|
||||||
"@semantic-release/commit-analyzer": "^11.1.0",
|
"@semantic-release/commit-analyzer": "^11.1.0",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
|
|
@ -46,13 +54,16 @@
|
||||||
"@semantic-release/npm": "^11.0.1",
|
"@semantic-release/npm": "^11.0.1",
|
||||||
"@semantic-release/release-notes-generator": "^12.1.0",
|
"@semantic-release/release-notes-generator": "^12.1.0",
|
||||||
"@t3-oss/env-nextjs": "^0.7.1",
|
"@t3-oss/env-nextjs": "^0.7.1",
|
||||||
"@vercel/otel": "^0.3.0",
|
"@vercel/otel": "^1.10.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"i18next": "^23.15.1",
|
||||||
|
"jaeger-client": "^3.19.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"next": "^14.0.3",
|
"next": "^14.0.3",
|
||||||
"next-compose-plugins": "^2.2.1",
|
"next-compose-plugins": "^2.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-i18next": "^15.0.1",
|
||||||
"tailwind-merge": "^2.0.0",
|
"tailwind-merge": "^2.0.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
|
|
@ -62,11 +73,11 @@
|
||||||
"@babel/plugin-transform-optional-chaining": "^7.23.4",
|
"@babel/plugin-transform-optional-chaining": "^7.23.4",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
||||||
"@jest/globals": "^29.7.0",
|
"@jest/globals": "^29.7.0",
|
||||||
"@opentelemetry/api": "1.7.0",
|
"@opentelemetry/api": "^1.9.0",
|
||||||
"@opentelemetry/resources": "1.18.1",
|
"@opentelemetry/resources": "^1.26.0",
|
||||||
"@opentelemetry/sdk-node": "0.45.1",
|
"@opentelemetry/sdk-node": "^0.53.0",
|
||||||
"@opentelemetry/sdk-trace-node": "1.18.1",
|
"@opentelemetry/sdk-trace-node": "^1.26.0",
|
||||||
"@opentelemetry/semantic-conventions": "1.18.1",
|
"@opentelemetry/semantic-conventions": "^1.27.0",
|
||||||
"@playwright/test": "^1.40.0",
|
"@playwright/test": "^1.40.0",
|
||||||
"@storybook/addon-essentials": "^7.5.3",
|
"@storybook/addon-essentials": "^7.5.3",
|
||||||
"@storybook/addon-interactions": "^7.5.3",
|
"@storybook/addon-interactions": "^7.5.3",
|
||||||
|
|
@ -74,7 +85,7 @@
|
||||||
"@storybook/blocks": "^7.5.3",
|
"@storybook/blocks": "^7.5.3",
|
||||||
"@storybook/nextjs": "^7.5.3",
|
"@storybook/nextjs": "^7.5.3",
|
||||||
"@storybook/react": "^7.5.3",
|
"@storybook/react": "^7.5.3",
|
||||||
"@storybook/test-runner": "^0.15.2",
|
"@storybook/test-runner": "^0.19.1",
|
||||||
"@storybook/testing-library": "^0.2.2",
|
"@storybook/testing-library": "^0.2.2",
|
||||||
"@testing-library/jest-dom": "^6.1.4",
|
"@testing-library/jest-dom": "^6.1.4",
|
||||||
"@testing-library/react": "^14.1.2",
|
"@testing-library/react": "^14.1.2",
|
||||||
|
|
@ -96,7 +107,7 @@
|
||||||
"eslint-plugin-react": "7.33.2",
|
"eslint-plugin-react": "7.33.2",
|
||||||
"eslint-plugin-storybook": "^0.6.15",
|
"eslint-plugin-storybook": "^0.6.15",
|
||||||
"eslint-plugin-tailwindcss": "^3.13.0",
|
"eslint-plugin-tailwindcss": "^3.13.0",
|
||||||
"fetch-mock": "^9.11.0",
|
"fetch-mock": "^11.1.3",
|
||||||
"gzip-size": "6",
|
"gzip-size": "6",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
|
|
@ -109,11 +120,11 @@
|
||||||
"prettier-plugin-tailwindcss": "^0.5.7",
|
"prettier-plugin-tailwindcss": "^0.5.7",
|
||||||
"semantic-release": "^22.0.8",
|
"semantic-release": "^22.0.8",
|
||||||
"storybook": "^7.5.3",
|
"storybook": "^7.5.3",
|
||||||
"tailwindcss": "^3.3.5",
|
"tailwindcss": "^3.4.12",
|
||||||
"ts-jest": "^29.1.1",
|
"ts-jest": "^29.1.1",
|
||||||
"tsc": "^2.0.4",
|
"tsc": "^2.0.4",
|
||||||
"typescript": "5.3.2",
|
"typescript": "5.3.2",
|
||||||
"webpack": "5.89.0"
|
"webpack": "^5.94.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.17.0"
|
"node": ">=18.17.0"
|
||||||
|
|
|
||||||
45
package/components/atoms/Button.tsx
Normal file
45
package/components/atoms/Button.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
"use client"
|
||||||
|
import { Button as MUIButton } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
interface ButtonProps {
|
||||||
|
label: string
|
||||||
|
variant?: "primary" | "secondary" | "success" | "danger" | "warning" | "info"
|
||||||
|
onClick?: () => void
|
||||||
|
disabled?: boolean
|
||||||
|
className?: string
|
||||||
|
startIcon?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const Button: React.FC<ButtonProps> = ({
|
||||||
|
label,
|
||||||
|
variant = "primary",
|
||||||
|
onClick,
|
||||||
|
disabled,
|
||||||
|
className = "",
|
||||||
|
startIcon,
|
||||||
|
}) => {
|
||||||
|
const colorMap: Record<string, "primary" | "secondary" | "error" | "warning" | "info" | "success"> = {
|
||||||
|
primary: "primary",
|
||||||
|
secondary: "secondary",
|
||||||
|
success: "success",
|
||||||
|
danger: "error",
|
||||||
|
warning: "warning",
|
||||||
|
info: "info",
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MUIButton
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled}
|
||||||
|
color={colorMap[variant ?? "primary"]}
|
||||||
|
className={className}
|
||||||
|
variant="contained"
|
||||||
|
startIcon={startIcon}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</MUIButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Button
|
||||||
27
package/components/atoms/Input.tsx
Normal file
27
package/components/atoms/Input.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
"use client"
|
||||||
|
import { TextField } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
interface InputProps {
|
||||||
|
type: string
|
||||||
|
placeholder?: string
|
||||||
|
value: string
|
||||||
|
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
|
autocomplete?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const Input: React.FC<InputProps> = ({ type, placeholder, value, onChange, autocomplete }) => {
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
type={type}
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
autoComplete={autocomplete}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Input
|
||||||
18
package/components/atoms/Label.tsx
Normal file
18
package/components/atoms/Label.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
"use client"
|
||||||
|
import { Typography } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
interface LabelProps {
|
||||||
|
htmlFor: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const Label: React.FC<LabelProps> = ({ htmlFor, text }) => {
|
||||||
|
return (
|
||||||
|
<Typography variant="subtitle1" component="label" htmlFor={htmlFor} className="mb-2 block">
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Label
|
||||||
18
package/components/atoms/Title.tsx
Normal file
18
package/components/atoms/Title.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
"use client"
|
||||||
|
import { Typography } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
interface TitleProps {
|
||||||
|
text: string
|
||||||
|
size?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
|
||||||
|
}
|
||||||
|
|
||||||
|
const Title: React.FC<TitleProps> = ({ text, size = "h1" }) => {
|
||||||
|
return (
|
||||||
|
<Typography variant={size} className="font-bold">
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Title
|
||||||
50
package/components/layouts/AskForAffiliation.tsx
Normal file
50
package/components/layouts/AskForAffiliation.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Card, CardContent } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
import Label from "@atoms/Label"
|
||||||
|
import Title from "@atoms/Title"
|
||||||
|
|
||||||
|
interface AskForAffiliationProps {
|
||||||
|
onAffiliationSelect: (isAffiliated: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AskForAffiliation: React.FC<AskForAffiliationProps> = ({ onAffiliationSelect }) => {
|
||||||
|
const handleYesClick = () => {
|
||||||
|
onAffiliationSelect(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNoClick = () => {
|
||||||
|
onAffiliationSelect(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={{ width: "100%", maxWidth: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100%",
|
||||||
|
p: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Title text="Se requiere Información" size="h3" />
|
||||||
|
<Label htmlFor="loyalty" text="¿Está registrado como afiliado?" />
|
||||||
|
<Box sx={{ mt: 3, display: "flex", gap: 3 }}>
|
||||||
|
<Grid size={{ xs: 6 }} sx={{ minWidth: "200px" }}>
|
||||||
|
<Button label="Sí" onClick={handleYesClick} variant="primary" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 6 }} sx={{ minWidth: "200px" }}>
|
||||||
|
<Button label="No" onClick={handleNoClick} variant="primary" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AskForAffiliation
|
||||||
110
package/components/layouts/IdentityDocumentNumber.tsx
Normal file
110
package/components/layouts/IdentityDocumentNumber.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Card, CardContent } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
import Input from "@atoms/Input"
|
||||||
|
import Title from "@atoms/Title"
|
||||||
|
|
||||||
|
interface IdentityDocumentNumberProps {
|
||||||
|
documentType: string
|
||||||
|
onSubmit: (documentNumber: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const IdentityDocumentNumber: React.FC<IdentityDocumentNumberProps> = ({ documentType, onSubmit }) => {
|
||||||
|
const [inputValue, setInputValue] = useState<string>("")
|
||||||
|
const [keyboardMode, setKeyboardMode] = useState<"numeric" | "alpha">("numeric")
|
||||||
|
const [isAlphaEnabled, setIsAlphaEnabled] = useState<boolean>(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const alphaDocuments = ["PASAPORTE", "CURP", "RFC", "NIE", "RUT"] // Documentos que contienen letras
|
||||||
|
setIsAlphaEnabled(alphaDocuments.includes(documentType.toUpperCase()))
|
||||||
|
setKeyboardMode(isAlphaEnabled ? "alpha" : "numeric")
|
||||||
|
}, [documentType, isAlphaEnabled])
|
||||||
|
|
||||||
|
const handleKeyPress = (key: string) => {
|
||||||
|
setInputValue((prev) => prev + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
setInputValue((prev) => prev.slice(0, -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderiza el teclado basado en el modo seleccionado
|
||||||
|
const renderKeyboard = () => {
|
||||||
|
if (keyboardMode === "numeric") {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"].map((num) => (
|
||||||
|
<Grid key={num} size={{ xs: 4 }}>
|
||||||
|
<Button label={num} onClick={() => handleKeyPress(num)} variant="primary" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{"ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((letter) => (
|
||||||
|
<Grid key={letter} size={{ xs: 2 }}>
|
||||||
|
<Button label={letter} onClick={() => handleKeyPress(letter)} variant="primary" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={{ width: "100%", maxWidth: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100%",
|
||||||
|
p: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Título */}
|
||||||
|
<Title text={`Ingrese el número de ${documentType}`} size="h4" />
|
||||||
|
|
||||||
|
{/* Input que muestra el valor actual */}
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder="Ingrese el número de documento"
|
||||||
|
value={inputValue}
|
||||||
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid container spacing={2} justifyContent="center" alignItems="center" sx={{ mt: 3 }}>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Button label="Borrar" onClick={handleDelete} variant="danger" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Button label="Cancelar" onClick={() => setInputValue("")} variant="danger" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
{renderKeyboard()}
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Button label="Ingresar" onClick={() => onSubmit(inputValue)} variant="success" className="h-16 w-full" />
|
||||||
|
</Grid>
|
||||||
|
{isAlphaEnabled && (
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Button
|
||||||
|
label={`Cambiar a ${keyboardMode === "numeric" ? "Alfabético" : "Numérico"}`}
|
||||||
|
onClick={() => setKeyboardMode(keyboardMode === "numeric" ? "alpha" : "numeric")}
|
||||||
|
variant="secondary"
|
||||||
|
className="h-16 w-full"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IdentityDocumentNumber
|
||||||
52
package/components/layouts/TypeIdentityDocument.tsx
Normal file
52
package/components/layouts/TypeIdentityDocument.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Card, CardContent } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
import Label from "@atoms/Label"
|
||||||
|
import Title from "@atoms/Title"
|
||||||
|
|
||||||
|
interface TypesDocumentProps {
|
||||||
|
typesDocument: string[]
|
||||||
|
onDocumentSelect: (documentType: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeIdentityDocument: React.FC<TypesDocumentProps> = ({ typesDocument, onDocumentSelect }) => {
|
||||||
|
const handleDocumentClick = (documentType: string) => {
|
||||||
|
onDocumentSelect(documentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={{ width: "100%", maxWidth: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100%",
|
||||||
|
p: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Title text="Se requiere Información" size="h4" />
|
||||||
|
<Label htmlFor="loyalty" text="Seleccione el tipo de documento de identidad" />
|
||||||
|
|
||||||
|
<Grid container spacing={2} justifyContent="center" sx={{ mt: 3 }}>
|
||||||
|
{typesDocument.map((documentType, index) => (
|
||||||
|
<Grid key={index} size={{ xs: 6, md: 4 }} sx={{ minWidth: "200px" }}>
|
||||||
|
<Button
|
||||||
|
label={documentType}
|
||||||
|
onClick={() => handleDocumentClick(documentType)}
|
||||||
|
variant="primary"
|
||||||
|
className="h-16 w-full"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TypeIdentityDocument
|
||||||
39
package/components/molecules/FormFields.tsx
Normal file
39
package/components/molecules/FormFields.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Box, FormControl } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
import Input from "@atoms/Input"
|
||||||
|
import Label from "@atoms/Label"
|
||||||
|
|
||||||
|
interface FormFieldProps {
|
||||||
|
label: string
|
||||||
|
inputType: string
|
||||||
|
inputValue: string
|
||||||
|
onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
|
placeholder?: string
|
||||||
|
autocomplete?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const FormField: React.FC<FormFieldProps> = ({
|
||||||
|
label,
|
||||||
|
inputType,
|
||||||
|
inputValue,
|
||||||
|
onInputChange,
|
||||||
|
placeholder,
|
||||||
|
autocomplete,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Box mb={2}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<Label htmlFor={label} text={label} />
|
||||||
|
<Input
|
||||||
|
type={inputType}
|
||||||
|
value={inputValue}
|
||||||
|
onChange={onInputChange}
|
||||||
|
placeholder={placeholder}
|
||||||
|
autocomplete={autocomplete}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormField
|
||||||
20
package/components/molecules/NumericKey.tsx
Normal file
20
package/components/molecules/NumericKey.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
"use client"
|
||||||
|
import Grid2 from "@mui/material/Grid2"
|
||||||
|
import React from "react"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
|
||||||
|
interface NumericKeyProps {
|
||||||
|
label: string | number
|
||||||
|
onClick: () => void
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const NumericKey: React.FC<NumericKeyProps> = ({ label, onClick, className }) => {
|
||||||
|
return (
|
||||||
|
<Grid2 container justifyContent="center" component="div">
|
||||||
|
<Button label={label.toString()} onClick={onClick} className={`h-16 w-full ${className}`} />
|
||||||
|
</Grid2>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NumericKey
|
||||||
69
package/components/molecules/NumericPad.tsx
Normal file
69
package/components/molecules/NumericPad.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
"use client"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import React from "react"
|
||||||
|
import NumericKey from "@molecules/NumericKey"
|
||||||
|
|
||||||
|
const NumericPad: React.FC = () => {
|
||||||
|
const handleKeyClick = (key: number) => {
|
||||||
|
console.log(`Key pressed: ${key}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container spacing={0.4} justifyContent="center" alignItems="center">
|
||||||
|
<Grid size={{ xs: 6 }}>
|
||||||
|
<NumericKey
|
||||||
|
label="Cancel"
|
||||||
|
onClick={() => console.log("Cancel pressed")}
|
||||||
|
className="h-12 w-full bg-danger-light text-white hover:bg-danger-dark"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 6 }}>
|
||||||
|
<NumericKey label="clear" onClick={() => console.log("Clear pressed")} className="size-12 bg-secondary-light" />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
<NumericKey
|
||||||
|
label="0"
|
||||||
|
onClick={() => console.log("0")}
|
||||||
|
className="size-24 bg-primary-500 text-white hover:bg-primary-600"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{[...Array(9).keys()].map((i) => (
|
||||||
|
<Grid key={i + 1} size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
{" "}
|
||||||
|
<NumericKey
|
||||||
|
label={i + 1}
|
||||||
|
onClick={() => handleKeyClick(i + 1)}
|
||||||
|
className="size-24 bg-primary-500 text-white hover:bg-primary-600"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
<NumericKey
|
||||||
|
label="."
|
||||||
|
onClick={() => console.log(".")}
|
||||||
|
className="size-24 bg-primary-500 text-white hover:bg-primary-600"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
<NumericKey label="/" onClick={() => console.log("Divide pressed")} className="size-12 bg-secondary-light" />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
<NumericKey label="QTY" onClick={() => console.log("QTY pressed")} className="size-12 bg-secondary-light" />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||||
|
<NumericKey label="Price" onClick={() => console.log("Price pressed")} className="size-12 bg-secondary-light" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid size={{ xs: 6 }}>
|
||||||
|
<NumericKey
|
||||||
|
label="Enter"
|
||||||
|
onClick={() => console.log("Enter pressed")}
|
||||||
|
className="h-12 w-full bg-success-light text-white hover:bg-success-dark"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NumericPad
|
||||||
28
package/components/molecules/PluEntry.tsx
Normal file
28
package/components/molecules/PluEntry.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
"use client"
|
||||||
|
import { Box } from "@mui/material"
|
||||||
|
import React, { useState } from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import Input from "@atoms/Input"
|
||||||
|
|
||||||
|
const PluEntry: React.FC = () => {
|
||||||
|
const [plu, setPlu] = useState("")
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setPlu(e.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ p: 1, backgroundColor: "#f5f5f5", borderRadius: 2 }}>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={plu}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
placeholder={t("lbl_enter_PLU")}
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluEntry
|
||||||
13
package/components/molecules/ProductMatch.tsx
Normal file
13
package/components/molecules/ProductMatch.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Typography } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const ProductMatch: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Box sx={{ p: 2, backgroundColor: "#f5f5f5", borderRadius: 1 }}>
|
||||||
|
<Typography variant="h6">Coincidencia de productos:</Typography> {/* TODO: Aquí irán los productos que coincidan con el PLU */}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductMatch
|
||||||
15
package/components/molecules/Screen.tsx
Normal file
15
package/components/molecules/Screen.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Typography } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const Screen: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Box sx={{ p: 2, backgroundColor: "#f5f5f5", borderRadius: 1, textAlign: "center" }}>{/* TODO: Logica para valores */}
|
||||||
|
<Typography variant="h6">Item Subtotal: $0.00</Typography>
|
||||||
|
<Typography variant="body1">Total Savings: $0.00</Typography>
|
||||||
|
<Typography variant="body1">Tax: $0.00</Typography>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Screen
|
||||||
310
package/components/organisms/ButtonPanel.tsx
Normal file
310
package/components/organisms/ButtonPanel.tsx
Normal file
|
|
@ -0,0 +1,310 @@
|
||||||
|
import AccountBalanceWalletIcon from "@mui/icons-material/AccountBalanceWallet"
|
||||||
|
import BackspaceIcon from "@mui/icons-material/Backspace"
|
||||||
|
import CreditCardIcon from "@mui/icons-material/CreditCard"
|
||||||
|
import DeleteIcon from "@mui/icons-material/Delete"
|
||||||
|
import DiscountIcon from "@mui/icons-material/Discount"
|
||||||
|
import LockIcon from "@mui/icons-material/Lock"
|
||||||
|
import PercentIcon from "@mui/icons-material/Percent"
|
||||||
|
import PlayArrowIcon from "@mui/icons-material/PlayArrow"
|
||||||
|
import ReceiptIcon from "@mui/icons-material/Receipt"
|
||||||
|
import RedeemIcon from "@mui/icons-material/Redeem"
|
||||||
|
import ReplayIcon from "@mui/icons-material/Replay"
|
||||||
|
import SearchIcon from "@mui/icons-material/Search"
|
||||||
|
import SettingsIcon from "@mui/icons-material/Settings"
|
||||||
|
import ShoppingBagIcon from "@mui/icons-material/ShoppingBag"
|
||||||
|
import ShoppingBasketIcon from "@mui/icons-material/ShoppingBasket"
|
||||||
|
import ShoppingCartIcon from "@mui/icons-material/ShoppingCart"
|
||||||
|
import StorefrontIcon from "@mui/icons-material/Storefront"
|
||||||
|
import TransferWithinAStationIcon from "@mui/icons-material/TransferWithinAStation"
|
||||||
|
import { Box, Card, CardContent } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import React from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
import { Tooltip } from "@atoms/Tooltip"
|
||||||
|
import ThemeToggle from "@styles/ThemeToggle"
|
||||||
|
|
||||||
|
|
||||||
|
const ButtonPanel: React.FC = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={{ height: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<ThemeToggle />
|
||||||
|
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer="Anula la orden actual" side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label="Void Order"
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="danger"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<ShoppingCartIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer="Void Last" side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label="Void Last"
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="danger"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<BackspaceIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_resume_previously_suspended_order")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label="Resume"
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<PlayArrowIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_transfer_Order_another_station")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_transfer_order")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<TransferWithinAStationIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_generate_resale")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_resale")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<StorefrontIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_generate_refund")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_returns")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<ReplayIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_add_receipt")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_add_receipt")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<ReceiptIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_manage_coupons")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_coupons")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<RedeemIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_manage_discount_percentage")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_discount_percentage")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<PercentIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_manage_amount_discount")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_amount_discount")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<DiscountIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("lbl_bag_fee")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("msj_bag_fee")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<ShoppingBagIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_bag_credit_management")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_bag_credit")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<ShoppingBasketIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_bottle_refund_management")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_bottle_refund")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<DeleteIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_tax_exemption_management")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_tax_exempt")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<CreditCardIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_delete_tax_exception")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_clear_exempt")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<CreditCardIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Tooltip explainer={t("msj_query_search_article")} side="top" withArrow>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label={t("lbl_item_inquiry")}
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<SearchIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 12 }} container spacing={1} justifyContent="center">
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label=""
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<SettingsIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label=""
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<AccountBalanceWalletIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4 }}>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label=""
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="primary"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<SearchIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Button
|
||||||
|
label=""
|
||||||
|
onClick={() => {}}
|
||||||
|
variant="warning"
|
||||||
|
className="full-size-button"
|
||||||
|
startIcon={<LockIcon />}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ButtonPanel
|
||||||
62
package/components/organisms/Header.tsx
Normal file
62
package/components/organisms/Header.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import MoreVertIcon from "@mui/icons-material/MoreVert"
|
||||||
|
import PersonIcon from "@mui/icons-material/Person"
|
||||||
|
import { Card, CardContent, CardHeader, IconButton, Typography } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import React from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
sx?: object
|
||||||
|
}
|
||||||
|
|
||||||
|
const Header: React.FC<HeaderProps> = ({ sx }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
return (
|
||||||
|
<Card sx={{ ...sx, p: 0.1 }}>
|
||||||
|
<CardHeader
|
||||||
|
title="Generic userd"
|
||||||
|
subheader="Add Member"
|
||||||
|
titleTypographyProps={{ color: "text.primary", fontWeight: "bold", fontSize: "1rem" }}
|
||||||
|
subheaderTypographyProps={{ color: "text.secondary", fontSize: "0.75rem" }}
|
||||||
|
sx={{ paddingBottom: 0 }}
|
||||||
|
/>
|
||||||
|
<CardContent sx={{ paddingTop: 0.2 }}>
|
||||||
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Fri, 13 Sept
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
9:36 am
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t('lbl_Store')}: <strong>8004</strong>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t('lbl_register')}: <strong>317</strong>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container alignItems="center">
|
||||||
|
<PersonIcon sx={{ color: "text.secondary", fontSize: "18px", mr: 0.9 }} /> {/* Icono más pequeño */}
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t('lbl_associate')} <strong>2</strong>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<IconButton size="small">
|
||||||
|
<MoreVertIcon color="action" sx={{ fontSize: "18px" }} />
|
||||||
|
</IconButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header
|
||||||
65
package/components/organisms/LoginForm.tsx
Normal file
65
package/components/organisms/LoginForm.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Typography } from "@mui/material"
|
||||||
|
import { useRouter } from "next/navigation"
|
||||||
|
import React, { useState } from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { auth } from "@app/account/controller/AuthController"
|
||||||
|
import Button from "@atoms/Button"
|
||||||
|
import Input from "@atoms/Input"
|
||||||
|
import Label from "@atoms/Label"
|
||||||
|
|
||||||
|
const LoginForm: React.FC = () => {
|
||||||
|
const [username, setUsername] = useState("")
|
||||||
|
const [password, setPassword] = useState("")
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const handleLogin = async () => {
|
||||||
|
const token = await auth(username, password)
|
||||||
|
if (token) {
|
||||||
|
router.push("/home")
|
||||||
|
} else {
|
||||||
|
setError( t("msj_Incorrect_credentials_try_again."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
handleLogin()
|
||||||
|
}}
|
||||||
|
sx={{ display: "flex", flexDirection: "column", gap: 3, width: "100%" }}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<Label htmlFor={t("lbl_username")} text={t("lbl_username")} />
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder={t("msj_enter_your_username")}
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
autocomplete="username"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Label htmlFor={t("lbl_password")} text={t("lbl_password")} />
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
placeholder={t("msj_enter_your_password")}
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
autocomplete="current-password"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{error && <Typography color="error">{error}</Typography>}
|
||||||
|
|
||||||
|
<Button label={t("lbl_login")} onClick={handleLogin} variant="primary" />
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoginForm
|
||||||
33
package/components/organisms/MainPanel.tsx
Normal file
33
package/components/organisms/MainPanel.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
"use client"
|
||||||
|
import { Card, CardContent } from "@mui/material"
|
||||||
|
import Grid from "@mui/material/Grid2"
|
||||||
|
import React from "react"
|
||||||
|
import NumericPad from "@molecules/NumericPad"
|
||||||
|
import PluEntry from "@molecules/PluEntry"
|
||||||
|
import ProductMatch from "@molecules/ProductMatch"
|
||||||
|
import Screen from "@molecules/Screen"
|
||||||
|
|
||||||
|
const MainPanel: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Card sx={{ height: "100%" }}>
|
||||||
|
<CardContent sx={{ padding: "8px" }}>
|
||||||
|
<Grid container spacing={1} justifyContent="center" alignItems="stretch">
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<Screen />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<ProductMatch />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<PluEntry />
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 12 }}>
|
||||||
|
<NumericPad />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MainPanel
|
||||||
47
package/components/organisms/Navbar.tsx
Normal file
47
package/components/organisms/Navbar.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
"use client";
|
||||||
|
import Grid from '@mui/material/Grid2';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
import Select from '@mui/material/Select';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import i18n from '@package/utils/language/i18n';
|
||||||
|
|
||||||
|
const Navbar: React.FC = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [language, setLanguage] = useState(i18n.language || 'en');
|
||||||
|
|
||||||
|
const changeLanguage = (lng: string) => {
|
||||||
|
i18n.changeLanguage(lng);
|
||||||
|
setLanguage(lng);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLanguage(i18n.language);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
className="bg-blue-600 text-white p-4"
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<h1 className="text-white font-bold">{t('lbl_wellcome')}</h1>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Select
|
||||||
|
value={language}
|
||||||
|
onChange={(e) => changeLanguage(e.target.value as string)}
|
||||||
|
variant="outlined"
|
||||||
|
className="bg-white text-black"
|
||||||
|
>
|
||||||
|
<MenuItem value="en">English</MenuItem>
|
||||||
|
<MenuItem value="es">Español</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Navbar;
|
||||||
28
package/components/organisms/ProductList.tsx
Normal file
28
package/components/organisms/ProductList.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
"use client"
|
||||||
|
import { Card, CardContent, Typography } from "@mui/material"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
const ProductList: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Card sx={{ height: "100%" }}>
|
||||||
|
{" "}
|
||||||
|
{/* Ajustar la altura de la Card */}
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" color="text.primary">
|
||||||
|
Lista de productos
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="text.secondary">
|
||||||
|
Producto 1
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="text.secondary">
|
||||||
|
Producto 2
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="text.secondary">
|
||||||
|
Producto 3
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductList
|
||||||
1
package/config/ApiPath.tsx
Normal file
1
package/config/ApiPath.tsx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const BASE_URL_AUTHENTICATION = "/AUTHENTICATION-SERVICE/rhi-bpc/"
|
||||||
32
package/config/FetchData.tsx
Normal file
32
package/config/FetchData.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { ReturnService } from "@package/config/ReturnService"
|
||||||
|
import i18n from "@package/utils/language/i18n"
|
||||||
|
|
||||||
|
const BASE_URL = process.env.NEXT_PUBLIC_API_URL
|
||||||
|
|
||||||
|
async function FetchData<T>(
|
||||||
|
BASE_URL_MODULE: string,
|
||||||
|
endpoint: string,
|
||||||
|
options: RequestInit = {}
|
||||||
|
): Promise<ReturnService<T>> {
|
||||||
|
const url = `${BASE_URL}${BASE_URL_MODULE}${endpoint}`
|
||||||
|
const text = i18n.t("errorProcessingAPI") as string
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, options)
|
||||||
|
|
||||||
|
if (response.status === 403) {
|
||||||
|
const text = i18n.t("inCorrectAccess") as string
|
||||||
|
return new ReturnService<T>(null as unknown as T, false, text, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return new ReturnService<T>(null as unknown as T, false, text, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
return new ReturnService<T>(data as T)
|
||||||
|
} catch (error: any) {
|
||||||
|
return new ReturnService<T>(null as unknown as T, false, text || error.message, error.errorCode || 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { FetchData }
|
||||||
13
package/config/ReturnService.tsx
Normal file
13
package/config/ReturnService.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export class ReturnService<T> {
|
||||||
|
correct: boolean
|
||||||
|
message: string
|
||||||
|
errorCode: number
|
||||||
|
object: T
|
||||||
|
|
||||||
|
constructor(object: T, correct = true, message = "", errorCode = 0) {
|
||||||
|
this.correct = correct
|
||||||
|
this.message = message
|
||||||
|
this.errorCode = errorCode
|
||||||
|
this.object = object
|
||||||
|
}
|
||||||
|
}
|
||||||
29
package/styles/ThemeToggle.tsx
Normal file
29
package/styles/ThemeToggle.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
"use client"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
const ThemeToggle: React.FC = () => {
|
||||||
|
const [theme, setTheme] = useState("light")
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const savedTheme = localStorage.getItem("theme")
|
||||||
|
if (savedTheme) {
|
||||||
|
setTheme(savedTheme)
|
||||||
|
document.documentElement.classList.toggle("dark", savedTheme === "dark")
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
const newTheme = theme === "light" ? "dark" : "light"
|
||||||
|
setTheme(newTheme)
|
||||||
|
localStorage.setItem("theme", newTheme)
|
||||||
|
document.documentElement.classList.toggle("dark", newTheme === "dark")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button onClick={toggleTheme} className="bg-primary rounded-lg p-2 text-white transition hover:bg-primary-600">
|
||||||
|
{theme === "light" ? "Modo Oscuro" : "Modo Claro"}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeToggle
|
||||||
9
package/styles/tailwind.css
Normal file
9
package/styles/tailwind.css
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
.full-size-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
63
package/utils/enums/TypesDocumentsByCountry.tsx
Normal file
63
package/utils/enums/TypesDocumentsByCountry.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
export enum ColombiaDocuments {
|
||||||
|
CEDULA_CIUDADANIA = "Cédula de Ciudadanía",
|
||||||
|
TARJETA_IDENTIDAD = "Tarjeta de Identidad",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
CEDULA_EXTRANJERIA = "Cédula de Extranjería",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum EcuadorDocuments {
|
||||||
|
CEDULA_IDENTIDAD = "Cédula de Identidad",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
RUC = "Registro Único de Contribuyentes (RUC)",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CostaRicaDocuments {
|
||||||
|
CEDULA_NACIONAL = "Cédula Nacional",
|
||||||
|
DIMEX = "Documento de Identificación de Migrantes Extranjeros (DIMEX)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ChileDocuments {
|
||||||
|
CEDULA_IDENTIDAD = "Cédula de Identidad",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
RUT = "Rol Único Tributario (RUT)",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MexicoDocuments {
|
||||||
|
CREDENCIAL_ELECTOR = "Credencial de Elector (INE)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
CURP = "Clave Única de Registro de Población (CURP)",
|
||||||
|
RFC = "Registro Federal de Contribuyentes (RFC)",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum USADocuments {
|
||||||
|
DRIVER_LICENSE = "Driver's License",
|
||||||
|
PASSPORT = "Passport",
|
||||||
|
SSN = "Social Security Number (SSN)",
|
||||||
|
STATE_ID = "State ID",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PeruDocuments {
|
||||||
|
DNI = "Documento Nacional de Identidad (DNI)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
CARNET_EXTRANJERIA = "Carnet de Extranjería",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ArgentinaDocuments {
|
||||||
|
DNI = "Documento Nacional de Identidad (DNI)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
CUIL = "Código Único de Identificación Laboral (CUIL)",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BrazilDocuments {
|
||||||
|
CPF = "Cadastro de Pessoas Físicas (CPF)",
|
||||||
|
RG = "Registro Geral (RG)",
|
||||||
|
CNH = "Carteira Nacional de Habilitação (CNH)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SpainDocuments {
|
||||||
|
DNI = "Documento Nacional de Identidad (DNI)",
|
||||||
|
NIE = "Número de Identificación de Extranjeros (NIE)",
|
||||||
|
PASAPORTE = "Pasaporte",
|
||||||
|
}
|
||||||
41
package/utils/getDocumentsByCountry.tsx
Normal file
41
package/utils/getDocumentsByCountry.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import {
|
||||||
|
ArgentinaDocuments,
|
||||||
|
BrazilDocuments,
|
||||||
|
ChileDocuments,
|
||||||
|
ColombiaDocuments,
|
||||||
|
CostaRicaDocuments,
|
||||||
|
EcuadorDocuments,
|
||||||
|
MexicoDocuments,
|
||||||
|
PeruDocuments,
|
||||||
|
SpainDocuments,
|
||||||
|
USADocuments,
|
||||||
|
} from "@package/utils/enums/TypesDocumentsByCountry"
|
||||||
|
|
||||||
|
const country = process.env.NEXT_PUBLIC_STORE_COUNTRY
|
||||||
|
|
||||||
|
export const getDocumentsByCountry = (): string[] => {
|
||||||
|
switch (country?.toLowerCase()) {
|
||||||
|
case "colombia":
|
||||||
|
return Object.values(ColombiaDocuments)
|
||||||
|
case "ecuador":
|
||||||
|
return Object.values(EcuadorDocuments)
|
||||||
|
case "costarica":
|
||||||
|
return Object.values(CostaRicaDocuments)
|
||||||
|
case "chile":
|
||||||
|
return Object.values(ChileDocuments)
|
||||||
|
case "mexico":
|
||||||
|
return Object.values(MexicoDocuments)
|
||||||
|
case "usa":
|
||||||
|
return Object.values(USADocuments)
|
||||||
|
case "peru":
|
||||||
|
return Object.values(PeruDocuments)
|
||||||
|
case "argentina":
|
||||||
|
return Object.values(ArgentinaDocuments)
|
||||||
|
case "brazil":
|
||||||
|
return Object.values(BrazilDocuments)
|
||||||
|
case "spain":
|
||||||
|
return Object.values(SpainDocuments)
|
||||||
|
default:
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
96
package/utils/language/i18n.tsx
Normal file
96
package/utils/language/i18n.tsx
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
import i18n from 'i18next';
|
||||||
|
import { initReactI18next } from 'react-i18next';
|
||||||
|
|
||||||
|
i18n
|
||||||
|
.use(initReactI18next)
|
||||||
|
.init({
|
||||||
|
fallbackLng: 'en', // Default language
|
||||||
|
lng: 'en', // Specify the default language to use
|
||||||
|
resources: {
|
||||||
|
en: {
|
||||||
|
translation: {
|
||||||
|
lbl_wellcome: "Welcome",
|
||||||
|
lbl_login: "Login",
|
||||||
|
lbl_username: "Username",
|
||||||
|
lbl_password: "Password",
|
||||||
|
lbl_enter_PLU: "Enter PLU",
|
||||||
|
lbl_transfer_order: "Transfer Order",
|
||||||
|
lbl_resale: "Resale",
|
||||||
|
lbl_add_receipt: "Add receipt",
|
||||||
|
lbl_coupons : "Coupons",
|
||||||
|
lbl_discount_percentage: "Discount percentage",
|
||||||
|
lbl_amount_discount: "Amount discount",
|
||||||
|
lbl_bag_credit: "Bag credit",
|
||||||
|
lbl_bottle_refund: "Bottle refund",
|
||||||
|
lbl_tax_exempt: "Tax exempt",
|
||||||
|
lbl_item_inquiry: "Item Inquiry",
|
||||||
|
lbl_Store: "Store",
|
||||||
|
lbl_register: "Register",
|
||||||
|
lbl_associate: "Associate",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
msj_resume_previously_suspended_order: "Resume a previously suspended order",
|
||||||
|
msj_transfer_Order_another_station: "Transfer an order to another station",
|
||||||
|
msj_generate_resale: "Generate a resale",
|
||||||
|
msj_generate_refund: "Generate a refund",
|
||||||
|
msj_add_receipt: "Add receipt",
|
||||||
|
msj_manage_coupons: "Manage coupons",
|
||||||
|
msj_manage_discount_percentage: "Manage discount percentage",
|
||||||
|
msj_manage_amount_discount: "Manage amount discount",
|
||||||
|
msj_bag_credit_management: "Credit bag management",
|
||||||
|
msj_bottle_refund_management: "Bottle refund management",
|
||||||
|
msj_tax_exemption_management: "Tax exemption management",
|
||||||
|
msj_query_search_article: "Query or search for article",
|
||||||
|
msj_enter_your_username: "Enter your username",
|
||||||
|
msj_enter_your_password: "Enter your password",
|
||||||
|
msj_Incorrect_credentials_try_again: "Incorrect credentials, try again",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
translation: {
|
||||||
|
lbl_wellcome: "Bienvenido",
|
||||||
|
lbl_login: "Iniciar sesión",
|
||||||
|
lbl_username: "Nombre de usuario",
|
||||||
|
lbl_password: "Contraseña",
|
||||||
|
lbl_enter_PLU: "Ingrese PLU",
|
||||||
|
lbl_transfer_order: "Transferir orden",
|
||||||
|
lbl_resale: "Reventa",
|
||||||
|
lbl_add_receipt: "Agregar recibo",
|
||||||
|
lbl_coupons : "Cupones",
|
||||||
|
lbl_discount_percentage: "Porcentaje de descuento",
|
||||||
|
lbl_amount_discount: "Importe de descuento",
|
||||||
|
lbl_bag_credit: "Bolsa de crédito",
|
||||||
|
lbl_bottle_refund: "Devolución de botellas",
|
||||||
|
lbl_tax_exempt: "Exento de impuestos",
|
||||||
|
lbl_item_inquiry: "Consulta de artículo",
|
||||||
|
lbl_Store: "Tienda",
|
||||||
|
lbl_register: "Registro",
|
||||||
|
lbl_associate: "Asociado",
|
||||||
|
|
||||||
|
|
||||||
|
msj_resume_previously_suspended_order: "Reanuda una orden previamente suspendida",
|
||||||
|
msj_transfer_Order_another_station: "Transfiere la orden a otra estación",
|
||||||
|
msj_generate_resale: "Generar una reventa",
|
||||||
|
msj_generate_refund: "Generar una devolución",
|
||||||
|
msj_add_receipt: "Agregar recibo",
|
||||||
|
msj_manage_coupons: "Administrar cupones",
|
||||||
|
msj_manage_discount_percentage: "Administrar porcentaje de descuento",
|
||||||
|
msj_manage_amount_discount: "Administrar importe de descuento",
|
||||||
|
msj_bag_credit_management: "Gestión de bolsa de crédito",
|
||||||
|
msj_bottle_refund_management: "Gestión de devolución de botellas",
|
||||||
|
msj_tax_exemption_management: "Gestión de exención de impuestos",
|
||||||
|
msj_query_search_article: "Consulta o búsqueda de artículo",
|
||||||
|
msj_enter_your_username: "Ingrese su nombre de usuario",
|
||||||
|
msj_enter_your_password: "Ingrese su contraseña",
|
||||||
|
msj_Incorrect_credentials_try_again: "Credenciales incorrectas, inténtelo de nuevo",
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false, // Not needed for React as it escapes by default
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
BIN
public/img/logo.png
Normal file
BIN
public/img/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
public/img/selfcheckout.jpg
Normal file
BIN
public/img/selfcheckout.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
|
|
@ -1,8 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": [
|
"extends": ["config:base"],
|
||||||
"config:base"
|
|
||||||
],
|
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
@ -12,7 +12,7 @@ module.exports = {
|
||||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
"./src/**/*.{js,ts,jsx,tsx,mdx}",
|
"./package/**/*.{js,ts,jsx,tsx}",
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
|
@ -29,62 +29,35 @@ module.exports = {
|
||||||
800: "#1e40af",
|
800: "#1e40af",
|
||||||
900: "#1e3a8a",
|
900: "#1e3a8a",
|
||||||
},
|
},
|
||||||
|
secondary: {
|
||||||
|
light: "#6b7280",
|
||||||
|
dark: "#374151",
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
light: "#10b981",
|
||||||
|
dark: "#047857",
|
||||||
|
},
|
||||||
|
danger: {
|
||||||
|
light: "#ef4444",
|
||||||
|
dark: "#b91c1c",
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
light: "#f59e0b",
|
||||||
|
dark: "#b45309",
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
light: "#0ea5e9",
|
||||||
|
dark: "#0369a1",
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
light: "#ffffff",
|
||||||
|
dark: "#111827",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
body: [
|
sans: ["Inter", "ui-sans-serif", "system-ui", "-apple-system", "Segoe UI", "Roboto", "Helvetica Neue", "Arial"],
|
||||||
"Inter",
|
|
||||||
"ui-sans-serif",
|
|
||||||
"system-ui",
|
|
||||||
"-apple-system",
|
|
||||||
"system-ui",
|
|
||||||
"Segoe UI",
|
|
||||||
"Roboto",
|
|
||||||
"Helvetica Neue",
|
|
||||||
"Arial",
|
|
||||||
"Noto Sans",
|
|
||||||
"sans-serif",
|
|
||||||
"Apple Color Emoji",
|
|
||||||
"Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol",
|
|
||||||
"Noto Color Emoji",
|
|
||||||
],
|
|
||||||
sans: [
|
|
||||||
"Inter",
|
|
||||||
"ui-sans-serif",
|
|
||||||
"system-ui",
|
|
||||||
"-apple-system",
|
|
||||||
"system-ui",
|
|
||||||
"Segoe UI",
|
|
||||||
"Roboto",
|
|
||||||
"Helvetica Neue",
|
|
||||||
"Arial",
|
|
||||||
"Noto Sans",
|
|
||||||
"sans-serif",
|
|
||||||
"Apple Color Emoji",
|
|
||||||
"Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol",
|
|
||||||
"Noto Color Emoji",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
borderWidth: {
|
|
||||||
DEFAULT: "1px",
|
|
||||||
0: "0",
|
|
||||||
2: "2px",
|
|
||||||
3: "3px",
|
|
||||||
4: "4px",
|
|
||||||
6: "6px",
|
|
||||||
8: "8px",
|
|
||||||
},
|
|
||||||
minHeight: {
|
|
||||||
...defaultTheme.height,
|
|
||||||
},
|
|
||||||
minWidth: {
|
|
||||||
...defaultTheme.width,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
future: {
|
|
||||||
hoverOnlyWhenSupported: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
"display": "Next.js",
|
"display": "Next.js",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "ES6",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
@ -17,14 +17,32 @@
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"baseUrl": ".",
|
|
||||||
"types": ["node", "jest", "@testing-library/jest-dom"],
|
"types": ["node", "jest", "@testing-library/jest-dom"],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "next"
|
"name": "next"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@atoms/*": ["./package/components/atoms/*"],
|
||||||
|
"@molecules/*": ["./package/components/molecules/*"],
|
||||||
|
"@organisms/*": ["./package/components/organisms/*"],
|
||||||
|
"@layouts/*": ["./package/components/layouts/*"],
|
||||||
|
"@styles/*": ["./package/styles/*"],
|
||||||
|
"@package/*": ["./package/*"],
|
||||||
|
"@app/*": ["./app/*"],
|
||||||
|
"@public/*": ["./public/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mjs", "jest.config.js", ".next/types/**/*.ts"],
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.mjs",
|
||||||
|
"jest.config.js",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
"package/config/FetchData.tsx"
|
||||||
|
],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue