Ref: modification components in selfcheckout
This commit is contained in:
parent
251a6a2a6a
commit
ab7a02bcca
40 changed files with 1315 additions and 557 deletions
63
package/components/molecules/ActionButtons.tsx
Normal file
63
package/components/molecules/ActionButtons.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
"use client";
|
||||
import { Box } from '@mui/material';
|
||||
import Grid from '@mui/material/Grid2';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from '@atoms/Button';
|
||||
|
||||
interface ActionButtonsProps {
|
||||
onVoidOrder: () => void;
|
||||
onVoidLast: () => void;
|
||||
onResume: () => void;
|
||||
}
|
||||
|
||||
const ActionButtons: React.FC<ActionButtonsProps> = ({ onVoidOrder, onVoidLast, onResume }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mb: 1,
|
||||
p: 1,
|
||||
boxShadow: 4,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
container
|
||||
spacing={2}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid size={{xs:4}}>
|
||||
<Button
|
||||
label={t("lbl_void_order")}
|
||||
variant="danger"
|
||||
onClick={onVoidOrder}
|
||||
className="full-width-button"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{xs:4}}>
|
||||
<Button
|
||||
label={t("lbl_void_last")}
|
||||
variant="danger"
|
||||
onClick={onVoidLast}
|
||||
className="full-width-button"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{xs:4}}>
|
||||
<Button
|
||||
label={t("lbl_resume")}
|
||||
variant="primary"
|
||||
onClick={onResume}
|
||||
className="full-width-button"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActionButtons;
|
||||
20
package/components/molecules/CustomCard.tsx
Normal file
20
package/components/molecules/CustomCard.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
"use client"
|
||||
import { CardContent, CardHeader, Card as MUICard } from "@mui/material"
|
||||
import React from "react"
|
||||
|
||||
interface CardProps {
|
||||
title?: string
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
const CustomCard: React.FC<CardProps> = ({ title, children, className }) => {
|
||||
return (
|
||||
<MUICard className={className}>
|
||||
{title && <CardHeader title={title} />}
|
||||
<CardContent>{children}</CardContent>
|
||||
</MUICard>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomCard
|
||||
|
|
@ -1,20 +1,24 @@
|
|||
"use client"
|
||||
import Grid2 from "@mui/material/Grid2"
|
||||
import React from "react"
|
||||
import Button from "@atoms/Button"
|
||||
"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
|
||||
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}`} />
|
||||
<Button
|
||||
label={label.toString()}
|
||||
onClick={onClick}
|
||||
className={`h-16 w-full text-3xl font-bold ${className}`}
|
||||
/>
|
||||
</Grid2>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default NumericKey
|
||||
export default NumericKey;
|
||||
|
|
|
|||
|
|
@ -1,69 +1,57 @@
|
|||
"use client"
|
||||
import Grid from "@mui/material/Grid2"
|
||||
import React from "react"
|
||||
import NumericKey from "@molecules/NumericKey"
|
||||
"use client";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import NumericKey from "@molecules/NumericKey";
|
||||
|
||||
const NumericPad: React.FC = () => {
|
||||
const handleKeyClick = (key: number) => {
|
||||
console.log(`Key pressed: ${key}`)
|
||||
}
|
||||
interface NumericPadProps {
|
||||
onKeyClick: (key: string) => void;
|
||||
}
|
||||
|
||||
const NumericPad: React.FC<NumericPadProps> = ({ onKeyClick }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Grid container spacing={0.4} justifyContent="center" alignItems="center">
|
||||
<Grid size={{ xs: 6 }}>
|
||||
<NumericKey
|
||||
label="Cancel"
|
||||
onClick={() => console.log("Cancel pressed")}
|
||||
label={t("lbl_cancel")}
|
||||
onClick={() => onKeyClick("cancel")}
|
||||
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"
|
||||
label={t("lbl_clear")}
|
||||
onClick={() => onKeyClick("clear")}
|
||||
className="h-12 bg-secondary-light text-black"
|
||||
/>
|
||||
</Grid>
|
||||
{[...Array(9).keys()].map((i) => (
|
||||
<Grid key={i + 1} size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||
{" "}
|
||||
{[...Array(10).keys()].map((i) => (
|
||||
<Grid key={i} size={{ xs: 4 }} sx={{ minWidth: "100px" }}>
|
||||
<NumericKey
|
||||
label={i + 1}
|
||||
onClick={() => handleKeyClick(i + 1)}
|
||||
className="size-24 bg-primary-500 text-white hover:bg-primary-600"
|
||||
label={i}
|
||||
onClick={() => onKeyClick(i.toString())}
|
||||
className="h-16 bg-primary-500 text-white hover:bg-primary-600"
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
<Grid size={{ xs: 3 }} sx={{ minWidth: "100px" }}>
|
||||
<Grid size={{ xs: 4 }}>
|
||||
<NumericKey
|
||||
label="."
|
||||
onClick={() => console.log(".")}
|
||||
className="size-24 bg-primary-500 text-white hover:bg-primary-600"
|
||||
onClick={() => onKeyClick(".")}
|
||||
className="h-16 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 }}>
|
||||
<Grid size={{ xs: 4 }}>
|
||||
<NumericKey
|
||||
label="Enter"
|
||||
onClick={() => console.log("Enter pressed")}
|
||||
label={t("lbl_enter")}
|
||||
onClick={() => onKeyClick("enter")}
|
||||
className="h-12 w-full bg-success-light text-white hover:bg-success-dark"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default NumericPad
|
||||
export default NumericPad;
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
"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
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
"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
|
||||
28
package/components/molecules/ProductRow.tsx
Normal file
28
package/components/molecules/ProductRow.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
"use client";
|
||||
|
||||
import { TableCell, TableRow } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
interface ProductRowProps {
|
||||
amount: number;
|
||||
name: string;
|
||||
unitValue: number;
|
||||
tax: number;
|
||||
discount: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
const ProductRow: React.FC<ProductRowProps> = ({ amount, name, unitValue, tax, discount, total }) => {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell>{amount}</TableCell>
|
||||
<TableCell>{name}</TableCell>
|
||||
<TableCell>${unitValue.toFixed(2)}</TableCell>
|
||||
<TableCell>${tax.toFixed(2)}</TableCell>
|
||||
<TableCell>${discount.toFixed(2)}</TableCell>
|
||||
<TableCell>${total.toFixed(2)}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductRow;
|
||||
50
package/components/molecules/ProductSearch.tsx
Normal file
50
package/components/molecules/ProductSearch.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// components/molecules/ProductSearch.tsx
|
||||
"use client";
|
||||
|
||||
import { Box } from '@mui/material';
|
||||
import Grid from '@mui/material/Grid2';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from '@atoms/Button';
|
||||
import Input from '@atoms/Input';
|
||||
|
||||
interface ProductSearchProps {
|
||||
onSearch: (plu: string) => void;
|
||||
}
|
||||
|
||||
const ProductSearch: React.FC<ProductSearchProps> = ({ onSearch }) => {
|
||||
const [plu, setPlu] = useState('');
|
||||
const { t } = useTranslation()
|
||||
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setPlu(e.target.value);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
onSearch(plu);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ p:1, mb: 1, boxShadow: '4' }}>
|
||||
<Grid container spacing={3} alignItems="center">
|
||||
<Grid size={{xs:8}}>
|
||||
<Input
|
||||
type="text"
|
||||
value={plu}
|
||||
placeholder={t("msj_enter_plu")}
|
||||
onChange={handleInputChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{xs:4}}>
|
||||
<Button label={t("lbl_search")} variant="primary" onClick={() => onSearch(plu)} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductSearch;
|
||||
92
package/components/molecules/SaleSummary.tsx
Normal file
92
package/components/molecules/SaleSummary.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
"use client";
|
||||
|
||||
import { Box, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';
|
||||
import Grid from '@mui/material/Grid2';
|
||||
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface SaleSummaryProps {
|
||||
subtotal: number;
|
||||
discount: number;
|
||||
tax: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
const SaleSummary: React.FC<SaleSummaryProps> = ({ subtotal, discount, tax, total }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
|
||||
color: 'black',
|
||||
borderRadius: '5px',
|
||||
boxShadow: '2',
|
||||
p: 1,
|
||||
mb: 1
|
||||
}}>
|
||||
<Box sx={{mb: 1, p: 1, boxShadow: '2', }}>
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell sx={{ color: 'primary', borderColor: 'black', fontWeight: 'bold', width: '30%' }}>{t("tle_product")}</TableCell>
|
||||
<TableCell sx={{ color: 'primary', borderColor: 'black', fontWeight: 'bold', width: '50%' }}>{t("tle_description")}</TableCell>
|
||||
<TableCell sx={{ color: 'primary', borderColor: 'black', fontWeight: 'bold', width: '20%', textAlign: 'right' }}>{t("tle_amount")}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell sx={{ color: 'black', borderColor: 'black' }}>Product R</TableCell>
|
||||
<TableCell sx={{ color: 'black', borderColor: 'black' }}>Producto para r uso</TableCell>
|
||||
<TableCell sx={{ color: 'black', borderColor: 'black', textAlign: 'right' }}>3</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Grid container justifyContent='right'>
|
||||
<Box sx={{ mt: 5, textAlign: 'right' }}>
|
||||
<Grid container>
|
||||
<Grid size={{xs:7}} sx={{ pr: 10 }}>
|
||||
<Typography variant="body2" align="right">{t("lbl_subtotal")}:</Typography>
|
||||
</Grid>
|
||||
<Grid size={{xs:5}}>
|
||||
<Typography variant="body2" align="left">$ 1.400</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid size={{xs:7}} sx={{ pr: 10 }}>
|
||||
<Typography variant="body2" align="right">{t("lbl_discount")}:</Typography>
|
||||
</Grid>
|
||||
<Grid size={{xs:5}}>
|
||||
<Typography variant="body2" align="left">$ 12</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid size={{xs:7}} sx={{ pr: 5.5 }}>
|
||||
<Typography variant="body2" align="right">{t("lbl_tax")}:</Typography>
|
||||
</Grid>
|
||||
<Grid size={{xs:5}}>
|
||||
<Typography variant="body2" align="left">$ 123</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid size={{xs:7}} sx={{ pr: 5.5 }}>
|
||||
<Typography variant="body2" align="right">{t("lbl_total")}:</Typography>
|
||||
</Grid>
|
||||
<Grid size={{xs:5}}>
|
||||
<Typography variant="body2" align="left">$ 1.511</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box sx={{ p: 3, boxShadow: '2' }}>
|
||||
<Typography variant="h6" sx={{ color: 'primary', display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span>{t("tle_total")}:</span>
|
||||
<span>$ 12.250</span>
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SaleSummary;
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
"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
|
||||
46
package/components/molecules/UserHeader.tsx
Normal file
46
package/components/molecules/UserHeader.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"use client";
|
||||
|
||||
import { Box } from '@mui/material';
|
||||
import Grid2 from '@mui/material/Grid2';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { useAtom } from 'jotai';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import UserAtom from '@atoms/states/UserAtom';
|
||||
|
||||
const UserHeader: React.FC = () => {
|
||||
const [user] = useAtom(UserAtom);
|
||||
const { t } = useTranslation()
|
||||
|
||||
|
||||
return (
|
||||
<Box sx={{mb: 1, boxShadow: '4', }}>
|
||||
<Grid2
|
||||
container
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
className="bg-blue-600 text-white p-4"
|
||||
>
|
||||
<Grid2>
|
||||
<Typography variant="h6" className="font-bold">
|
||||
{user ? `${t("lbl_name_customer")}: ${user.name} ${user.lastName}` : `${t("lbl_name_customer")}: Anónimo`}
|
||||
</Typography>
|
||||
</Grid2>
|
||||
|
||||
<Grid2>
|
||||
<Typography variant="body2" color="textSecondary" className="text-white">
|
||||
{user ? `${t("lbl_dni_customer")}: ${user.idTypeUser}` : `${t("lbl_dni_customer")}: 222222222222`}
|
||||
</Typography>
|
||||
</Grid2>
|
||||
|
||||
<Grid2>
|
||||
<Typography variant="body2" className="text-white">
|
||||
{user ? `${t("lbl_email_customer")}: ${user.email}` : `${t("lbl_email_customer")}: generic@example.com`}
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserHeader;
|
||||
Loading…
Add table
Add a link
Reference in a new issue