feat: integrate bottom toolbar store in various organization profile pages
- Added bottom toolbar functionality to the Schedules, Services, Templates, and WAP pages. - Ensured the bottom toolbar is cleared on component unmount. - Improved code formatting and consistency across components. - Minor adjustments to state management and event handling for better clarity and performance.
This commit is contained in:
+316
-147
@@ -23,6 +23,7 @@ import { CLIENT_ACCOUNT_MOVEMENT_TYPES } from "@core/Models/ClientAccountMovemen
|
|||||||
import { getPaymentIcon } from "@core/app/components/PaymentIcons/PaymentIcons";
|
import { getPaymentIcon } from "@core/app/components/PaymentIcons/PaymentIcons";
|
||||||
import SecureByPlan, { SECURE_CONTENTS } from "@core/app/components/SecureByPlan/SecureByPlan";
|
import SecureByPlan, { SECURE_CONTENTS } from "@core/app/components/SecureByPlan/SecureByPlan";
|
||||||
import { motion } from "motion/react";
|
import { motion } from "motion/react";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -36,6 +37,7 @@ export default function ClientAccount() {
|
|||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
|
|
||||||
@@ -68,6 +70,8 @@ export default function ClientAccount() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/clients",
|
url: "/admin/org/profile/" + id + "/clients",
|
||||||
title: "Clientes",
|
title: "Clientes",
|
||||||
@@ -85,6 +89,10 @@ export default function ClientAccount() {
|
|||||||
title: "Cuenta Corriente",
|
title: "Cuenta Corriente",
|
||||||
icon: <AccountBalanceOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <AccountBalanceOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -127,149 +135,273 @@ export default function ClientAccount() {
|
|||||||
|
|
||||||
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
||||||
<div style={{ maxWidth: "800px", margin: "0 auto", paddingBottom: "100px" }}>
|
<div style={{ maxWidth: "800px", margin: "0 auto", paddingBottom: "100px" }}>
|
||||||
|
|
||||||
{/* Top Status Card */}
|
{/* Top Status Card */}
|
||||||
<div style={{ position: "sticky", top: "70px", zIndex: 100, display: "flex", flexDirection: "column", background: "white", paddingBottom: "20px", paddingTop: "5px", margin: "0 -10px 30px -10px", paddingLeft: "10px", paddingRight: "10px" }}>
|
<div
|
||||||
{view && (
|
style={{
|
||||||
<motion.div
|
position: "sticky",
|
||||||
layout
|
top: "70px",
|
||||||
initial={{ opacity: 0, y: -20 }}
|
zIndex: 100,
|
||||||
animate={{
|
display: "flex",
|
||||||
opacity: 1,
|
flexDirection: "column",
|
||||||
y: 0,
|
background: "white",
|
||||||
padding: isMinimized ? "25px 50px" : "40px 20px",
|
paddingBottom: "20px",
|
||||||
borderRadius: isMinimized ? "15px" : "20px"
|
paddingTop: "5px",
|
||||||
}}
|
margin: "0 -10px 30px -10px",
|
||||||
style={{
|
paddingLeft: "10px",
|
||||||
display: "flex",
|
paddingRight: "10px",
|
||||||
flexDirection: isMinimized ? "row" : "column",
|
}}
|
||||||
alignItems: "center",
|
>
|
||||||
justifyContent: isMinimized ? "space-between" : "center",
|
{view && (
|
||||||
background: view.amount >= 0
|
|
||||||
? "linear-gradient(135deg, #1d976c 0%, #93f9b9 100%)"
|
|
||||||
: "linear-gradient(135deg, #cb2d3e 0%, #ef473a 100%)",
|
|
||||||
color: "white",
|
|
||||||
boxShadow: isMinimized ? "0 4px 15px rgba(0,0,0,0.3)" : "0 10px 30px rgba(0,0,0,0.15)",
|
|
||||||
position: "relative",
|
|
||||||
overflow: "hidden",
|
|
||||||
transition: "box-shadow 0.3s ease"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
onClick={() => setForceMinimized(!forceMinimized)}
|
|
||||||
style={{ position: "absolute", top: "10px", left: "10px", color: "rgba(255,255,255,0.7)", zIndex: 10 }}
|
|
||||||
size="small"
|
|
||||||
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
|
||||||
>
|
|
||||||
{forceMinimized ? <UnfoldMoreIcon /> : <UnfoldLessIcon />}
|
|
||||||
</IconButton>
|
|
||||||
|
|
||||||
{/* Decorative background circles */}
|
|
||||||
<div style={{ position: "absolute", top: "-50px", right: "-50px", width: "150px", height: "150px", borderRadius: "50%", background: "rgba(255,255,255,0.1)" }}></div>
|
|
||||||
<div style={{ position: "absolute", bottom: "-30px", left: "-30px", width: "100px", height: "100px", borderRadius: "50%", background: "rgba(255,255,255,0.1)" }}></div>
|
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
|
layout
|
||||||
|
initial={{ opacity: 0, y: -20 }}
|
||||||
animate={{
|
animate={{
|
||||||
fontSize: isMinimized ? "14px" : "16px",
|
opacity: 1,
|
||||||
marginBottom: isMinimized ? "0px" : "0px",
|
y: 0,
|
||||||
marginLeft: isMinimized ? "30px" : "0px"
|
padding: isMinimized ? "25px 50px" : "40px 20px",
|
||||||
|
borderRadius: isMinimized ? "15px" : "20px",
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "bold", opacity: 0.9, textTransform: "uppercase", letterSpacing: "1px" }}
|
style={{
|
||||||
>
|
display: "flex",
|
||||||
Saldo Actual
|
flexDirection: isMinimized ? "row" : "column",
|
||||||
</motion.div>
|
alignItems: "center",
|
||||||
<motion.div
|
justifyContent: isMinimized ? "space-between" : "center",
|
||||||
animate={{
|
background:
|
||||||
fontSize: isMinimized ? "24px" : "56px",
|
view.amount >= 0
|
||||||
margin: isMinimized ? "0px" : "10px 0 30px 0"
|
? "linear-gradient(135deg, #1d976c 0%, #93f9b9 100%)"
|
||||||
|
: "linear-gradient(135deg, #cb2d3e 0%, #ef473a 100%)",
|
||||||
|
color: "white",
|
||||||
|
boxShadow: isMinimized
|
||||||
|
? "0 4px 15px rgba(0,0,0,0.3)"
|
||||||
|
: "0 10px 30px rgba(0,0,0,0.15)",
|
||||||
|
position: "relative",
|
||||||
|
overflow: "hidden",
|
||||||
|
transition: "box-shadow 0.3s ease",
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "900", textShadow: "0 2px 10px rgba(0,0,0,0.1)" }}
|
|
||||||
>
|
>
|
||||||
{formatPrice(view.amount)}
|
<IconButton
|
||||||
</motion.div>
|
onClick={() => setForceMinimized(!forceMinimized)}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
{!isMinimized && (
|
top: "10px",
|
||||||
<motion.div
|
left: "10px",
|
||||||
initial={{ opacity: 0 }}
|
color: "rgba(255,255,255,0.7)",
|
||||||
animate={{ opacity: 1 }}
|
zIndex: 10,
|
||||||
exit={{ opacity: 0 }}
|
}}
|
||||||
style={{ display: "flex", gap: "15px", flexDirection: "row", zIndex: 1 }}
|
size="small"
|
||||||
|
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
||||||
>
|
>
|
||||||
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
{forceMinimized ? <UnfoldMoreIcon /> : <UnfoldLessIcon />}
|
||||||
<IconButton
|
</IconButton>
|
||||||
sx={{
|
|
||||||
backgroundColor: "rgba(255,255,255,0.2)",
|
|
||||||
color: "white",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "110px",
|
|
||||||
height: "90px",
|
|
||||||
borderRadius: "15px",
|
|
||||||
"&:hover": { backgroundColor: "rgba(255,255,255,0.3)" }
|
|
||||||
}}
|
|
||||||
onClick={() => add(CLIENT_ACCOUNT_MOVEMENT_TYPES.DEPOSIT)}
|
|
||||||
>
|
|
||||||
<DepositarIcon sx={{ fontSize: "32px", marginBottom: "5px" }} />
|
|
||||||
<span style={{ fontSize: "14px", fontWeight: "bold" }}>Ingresar</span>
|
|
||||||
</IconButton>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
{/* Decorative background circles */}
|
||||||
<IconButton
|
<div
|
||||||
sx={{
|
style={{
|
||||||
backgroundColor: "rgba(255,255,255,0.2)",
|
position: "absolute",
|
||||||
color: "white",
|
top: "-50px",
|
||||||
display: "flex",
|
right: "-50px",
|
||||||
alignItems: "center",
|
width: "150px",
|
||||||
flexDirection: "column",
|
height: "150px",
|
||||||
width: "110px",
|
borderRadius: "50%",
|
||||||
height: "90px",
|
background: "rgba(255,255,255,0.1)",
|
||||||
borderRadius: "15px",
|
}}
|
||||||
"&:hover": { backgroundColor: "rgba(255,255,255,0.3)" }
|
></div>
|
||||||
}}
|
<div
|
||||||
onClick={() => add(CLIENT_ACCOUNT_MOVEMENT_TYPES.WITHDRAWAL)}
|
style={{
|
||||||
>
|
position: "absolute",
|
||||||
<RetirarIcon sx={{ fontSize: "32px", marginBottom: "5px" }} />
|
bottom: "-30px",
|
||||||
<span style={{ fontSize: "14px", fontWeight: "bold" }}>Retirar</span>
|
left: "-30px",
|
||||||
</IconButton>
|
width: "100px",
|
||||||
</motion.div>
|
height: "100px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "rgba(255,255,255,0.1)",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
<motion.div
|
||||||
<IconButton
|
animate={{
|
||||||
sx={{
|
fontSize: isMinimized ? "14px" : "16px",
|
||||||
backgroundColor: "white",
|
marginBottom: isMinimized ? "0px" : "0px",
|
||||||
color: view.amount >= 0 ? "#1d976c" : "#cb2d3e",
|
marginLeft: isMinimized ? "30px" : "0px",
|
||||||
display: "flex",
|
}}
|
||||||
alignItems: "center",
|
style={{
|
||||||
flexDirection: "column",
|
fontWeight: "bold",
|
||||||
width: "110px",
|
opacity: 0.9,
|
||||||
height: "90px",
|
textTransform: "uppercase",
|
||||||
borderRadius: "15px",
|
letterSpacing: "1px",
|
||||||
boxShadow: "0 4px 15px rgba(0,0,0,0.1)",
|
}}
|
||||||
"&:hover": { backgroundColor: "#f8f9fa" }
|
>
|
||||||
}}
|
Saldo Actual
|
||||||
onClick={() => goTo("/admin/org/" + id + "/client/" + clientId + "/account/movements")}
|
|
||||||
>
|
|
||||||
<MovimientosIcon sx={{ fontSize: "32px", marginBottom: "5px" }} />
|
|
||||||
<span style={{ fontSize: "14px", fontWeight: "bold" }}>Historial</span>
|
|
||||||
</IconButton>
|
|
||||||
</motion.div>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
<motion.div
|
||||||
</motion.div>
|
animate={{
|
||||||
)}
|
fontSize: isMinimized ? "24px" : "56px",
|
||||||
|
margin: isMinimized ? "0px" : "10px 0 30px 0",
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
fontWeight: "900",
|
||||||
|
textShadow: "0 2px 10px rgba(0,0,0,0.1)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatPrice(view.amount)}
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{!isMinimized && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "15px",
|
||||||
|
flexDirection: "row",
|
||||||
|
zIndex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "rgba(255,255,255,0.2)",
|
||||||
|
color: "white",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "110px",
|
||||||
|
height: "90px",
|
||||||
|
borderRadius: "15px",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(255,255,255,0.3)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
add(CLIENT_ACCOUNT_MOVEMENT_TYPES.DEPOSIT)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<DepositarIcon
|
||||||
|
sx={{ fontSize: "32px", marginBottom: "5px" }}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
style={{ fontSize: "14px", fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
Ingresar
|
||||||
|
</span>
|
||||||
|
</IconButton>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "rgba(255,255,255,0.2)",
|
||||||
|
color: "white",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "110px",
|
||||||
|
height: "90px",
|
||||||
|
borderRadius: "15px",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(255,255,255,0.3)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
add(CLIENT_ACCOUNT_MOVEMENT_TYPES.WITHDRAWAL)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<RetirarIcon
|
||||||
|
sx={{ fontSize: "32px", marginBottom: "5px" }}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
style={{ fontSize: "14px", fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
Retirar
|
||||||
|
</span>
|
||||||
|
</IconButton>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
color: view.amount >= 0 ? "#1d976c" : "#cb2d3e",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "110px",
|
||||||
|
height: "90px",
|
||||||
|
borderRadius: "15px",
|
||||||
|
boxShadow: "0 4px 15px rgba(0,0,0,0.1)",
|
||||||
|
"&:hover": { backgroundColor: "#f8f9fa" },
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
goTo(
|
||||||
|
"/admin/org/" +
|
||||||
|
id +
|
||||||
|
"/client/" +
|
||||||
|
clientId +
|
||||||
|
"/account/movements",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MovimientosIcon
|
||||||
|
sx={{ fontSize: "32px", marginBottom: "5px" }}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
style={{ fontSize: "14px", fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
Historial
|
||||||
|
</span>
|
||||||
|
</IconButton>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "15px", padding: "0 10px" }}>
|
<div
|
||||||
<div style={{ fontSize: "20px", fontWeight: "bold", color: "var(--black-light)" }}>
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: "15px",
|
||||||
|
padding: "0 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "20px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "var(--black-light)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
Últimos Movimientos
|
Últimos Movimientos
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{ fontSize: "14px", color: "var(--wine-dark)", cursor: "pointer", fontWeight: "bold" }}
|
style={{
|
||||||
onClick={() => goTo("/admin/org/" + id + "/client/" + clientId + "/account/movements")}
|
fontSize: "14px",
|
||||||
|
color: "var(--wine-dark)",
|
||||||
|
cursor: "pointer",
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
goTo(
|
||||||
|
"/admin/org/" +
|
||||||
|
id +
|
||||||
|
"/client/" +
|
||||||
|
clientId +
|
||||||
|
"/account/movements",
|
||||||
|
)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Ver todos
|
Ver todos
|
||||||
</div>
|
</div>
|
||||||
@@ -294,42 +426,79 @@ export default function ClientAccount() {
|
|||||||
boxShadow: "0 2px 8px rgba(0,0,0,0.05)",
|
boxShadow: "0 2px 8px rgba(0,0,0,0.05)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
<div
|
||||||
<div style={{
|
style={{
|
||||||
width: "45px",
|
|
||||||
height: "45px",
|
|
||||||
borderRadius: "12px",
|
|
||||||
backgroundColor: movement.amount > 0 ? "rgba(40, 167, 69, 0.1)" : "rgba(220, 53, 69, 0.1)",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
gap: "15px",
|
||||||
color: movement.amount > 0 ? "#28a745" : "#dc3545"
|
}}
|
||||||
}}>
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "45px",
|
||||||
|
height: "45px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
backgroundColor:
|
||||||
|
movement.amount > 0
|
||||||
|
? "rgba(40, 167, 69, 0.1)"
|
||||||
|
: "rgba(220, 53, 69, 0.1)",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
color:
|
||||||
|
movement.amount > 0 ? "#28a745" : "#dc3545",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{getPaymentIcon(movement.paymentMethod)}
|
{getPaymentIcon(movement.paymentMethod)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontSize: "16px", fontWeight: "bold", color: "#333", marginBottom: "3px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "16px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333",
|
||||||
|
marginBottom: "3px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{movement.description}
|
{movement.description}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: "13px", color: "#888" }}>
|
<div style={{ fontSize: "13px", color: "#888" }}>
|
||||||
{dayjs(movement.createdAt).format("DD MMMM YYYY • HH:mm")}
|
{dayjs(movement.createdAt).format(
|
||||||
|
"DD MMMM YYYY • HH:mm",
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div
|
||||||
fontSize: "18px",
|
style={{
|
||||||
fontWeight: "900",
|
fontSize: "18px",
|
||||||
color: movement.amount > 0 ? "#28a745" : "#dc3545",
|
fontWeight: "900",
|
||||||
}}>
|
color: movement.amount > 0 ? "#28a745" : "#dc3545",
|
||||||
{movement.amount > 0 ? "+" : ""}{formatPrice(movement.amount)}
|
}}
|
||||||
|
>
|
||||||
|
{movement.amount > 0 ? "+" : ""}
|
||||||
|
{formatPrice(movement.amount)}
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ textAlign: "center", padding: "40px", backgroundColor: "#fff", borderRadius: "15px", color: "#888", border: "1px dashed #ccc" }}>
|
<div
|
||||||
<AccountBalanceOutlinedIcon sx={{ fontSize: "48px", color: "#ddd", marginBottom: "10px" }} />
|
style={{
|
||||||
<div style={{ fontSize: "16px", fontWeight: "bold", color: "#666" }}>
|
textAlign: "center",
|
||||||
|
padding: "40px",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderRadius: "15px",
|
||||||
|
color: "#888",
|
||||||
|
border: "1px dashed #ccc",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccountBalanceOutlinedIcon
|
||||||
|
sx={{ fontSize: "48px", color: "#ddd", marginBottom: "10px" }}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{ fontSize: "16px", fontWeight: "bold", color: "#666" }}
|
||||||
|
>
|
||||||
Aún no hay movimientos
|
Aún no hay movimientos
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: "14px" }}>
|
<div style={{ fontSize: "14px" }}>
|
||||||
|
|||||||
+24
-18
@@ -1,9 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useAlert } from "@core/Store/Alert.Store";
|
import { useAlert } from "@core/Store/Alert.Store";
|
||||||
import {
|
import { useEventHandlerStore, EVENT_TYPES } from "@core/Store/EventHandler.Store";
|
||||||
useEventHandlerStore,
|
|
||||||
EVENT_TYPES,
|
|
||||||
} from "@core/Store/EventHandler.Store";
|
|
||||||
import { useLocationStore } from "@core/Store/Location.Store";
|
import { useLocationStore } from "@core/Store/Location.Store";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
@@ -14,6 +11,7 @@ import ServiceItem from "@core/app/components/ServiceItem/ServiceItem";
|
|||||||
import Location from "@core/app/components/Location/Location";
|
import Location from "@core/app/components/Location/Location";
|
||||||
import { useNavigation } from "@core/app/hooks/goto";
|
import { useNavigation } from "@core/app/hooks/goto";
|
||||||
import { useMenuStore } from "@core/Store/Menu.Store";
|
import { useMenuStore } from "@core/Store/Menu.Store";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -26,14 +24,14 @@ export default function ClientAppointments() {
|
|||||||
const clientId = data.clientId;
|
const clientId = data.clientId;
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const menu = useMenuStore();
|
const menu = useMenuStore();
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
|
|
||||||
const [appintments, setAppointments] =
|
const [appintments, setAppointments] = useState<AppointmentAdminByClientView>({
|
||||||
useState<AppointmentAdminByClientView>({
|
events: [],
|
||||||
events: [],
|
});
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -44,6 +42,8 @@ export default function ClientAppointments() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/clients",
|
url: "/admin/org/profile/" + id + "/clients",
|
||||||
title: "Clientes",
|
title: "Clientes",
|
||||||
@@ -61,6 +61,10 @@ export default function ClientAppointments() {
|
|||||||
title: "Turnos reservados",
|
title: "Turnos reservados",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -89,15 +93,17 @@ export default function ClientAppointments() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{appintments.events.length === 0 ? (
|
{appintments.events.length === 0 ? (
|
||||||
<div style={{
|
<div
|
||||||
gridColumn: "1 / -1",
|
style={{
|
||||||
textAlign: "center",
|
gridColumn: "1 / -1",
|
||||||
padding: "40px 20px",
|
textAlign: "center",
|
||||||
background: "#fff",
|
padding: "40px 20px",
|
||||||
borderRadius: "12px",
|
background: "#fff",
|
||||||
boxShadow: "0 4px 15px rgba(0,0,0,0.02)",
|
borderRadius: "12px",
|
||||||
color: "#7f8c8d"
|
boxShadow: "0 4px 15px rgba(0,0,0,0.02)",
|
||||||
}}>
|
color: "#7f8c8d",
|
||||||
|
}}
|
||||||
|
>
|
||||||
No hay turnos registrados para este cliente.
|
No hay turnos registrados para este cliente.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -113,7 +119,7 @@ export default function ClientAppointments() {
|
|||||||
"/client/" +
|
"/client/" +
|
||||||
clientId +
|
clientId +
|
||||||
"/appointments/" +
|
"/appointments/" +
|
||||||
event.id
|
event.id,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { validatePhone } from "@core/helpers/validatePhone";
|
|||||||
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
||||||
import Switch from "@core/app/components/Switch/Switch";
|
import Switch from "@core/app/components/Switch/Switch";
|
||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -29,6 +30,7 @@ export default function ClientCreate() {
|
|||||||
const confirm = useConfirmStore();
|
const confirm = useConfirmStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const [firstName, setFirstName] = useState("");
|
const [firstName, setFirstName] = useState("");
|
||||||
const [lastName, setLastName] = useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
@@ -46,6 +48,8 @@ export default function ClientCreate() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/clients",
|
url: "/admin/org/profile/" + id + "/clients",
|
||||||
title: "Clientes",
|
title: "Clientes",
|
||||||
@@ -63,6 +67,10 @@ export default function ClientCreate() {
|
|||||||
title: "Editar",
|
title: "Editar",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -92,7 +100,7 @@ export default function ClientCreate() {
|
|||||||
confirm.show(
|
confirm.show(
|
||||||
validationPhoneResult.message,
|
validationPhoneResult.message,
|
||||||
() => {},
|
() => {},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
return;
|
return;
|
||||||
@@ -112,7 +120,7 @@ export default function ClientCreate() {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
alert.showSuccess(
|
alert.showSuccess(
|
||||||
`Información del cliente ${firstName} ${lastName} actualizada`
|
`Información del cliente ${firstName} ${lastName} actualizada`,
|
||||||
);
|
);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
goTo("/admin/org/" + id + "/client/" + clientId + "/profile");
|
goTo("/admin/org/" + id + "/client/" + clientId + "/profile");
|
||||||
@@ -180,7 +188,9 @@ export default function ClientCreate() {
|
|||||||
/>
|
/>
|
||||||
<div style={{ marginTop: "15px" }}></div>
|
<div style={{ marginTop: "15px" }}></div>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||||
<Typography variant="body1" sx={{ fontWeight: "bold", paddingLeft: "10px" }}>Baneado (No puede reservar)</Typography>
|
<Typography variant="body1" sx={{ fontWeight: "bold", paddingLeft: "10px" }}>
|
||||||
|
Baneado (No puede reservar)
|
||||||
|
</Typography>
|
||||||
<Switch
|
<Switch
|
||||||
checked={banned}
|
checked={banned}
|
||||||
onChange={(checked) => {
|
onChange={(checked) => {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { ClientMergeParams, OrganizationClientView } from "@core/Models/Clients.
|
|||||||
import Button from "@core/app/components/Button/Button";
|
import Button from "@core/app/components/Button/Button";
|
||||||
import MaterialAlert from "@mui/material/Alert";
|
import MaterialAlert from "@mui/material/Alert";
|
||||||
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -32,6 +33,7 @@ export default function ClientCreate() {
|
|||||||
const confirm = useConfirmStore();
|
const confirm = useConfirmStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ export default function ClientCreate() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [clientMergeFilterData, setClientMergeFilterData] = useState<TextObjectFilterResult[]>(
|
const [clientMergeFilterData, setClientMergeFilterData] = useState<TextObjectFilterResult[]>(
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
const [clientMergeId, setClientMergeId] = useState<string>("");
|
const [clientMergeId, setClientMergeId] = useState<string>("");
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ export default function ClientCreate() {
|
|||||||
() => {
|
() => {
|
||||||
mergeClients();
|
mergeClients();
|
||||||
},
|
},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,6 +107,8 @@ export default function ClientCreate() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/clients",
|
url: "/admin/org/profile/" + id + "/clients",
|
||||||
title: "Clientes",
|
title: "Clientes",
|
||||||
@@ -122,6 +126,10 @@ export default function ClientCreate() {
|
|||||||
title: "Fusionar clientes",
|
title: "Fusionar clientes",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
+31
-13
@@ -11,6 +11,7 @@ import ClientsIcon from "@mui/icons-material/AccountBoxOutlined";
|
|||||||
import NotificationsIcon from "@mui/icons-material/NotificationsOutlined";
|
import NotificationsIcon from "@mui/icons-material/NotificationsOutlined";
|
||||||
import MaterialAlert from "@mui/material/Alert";
|
import MaterialAlert from "@mui/material/Alert";
|
||||||
import styles from "./NotificationsPage.module.css";
|
import styles from "./NotificationsPage.module.css";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -20,7 +21,7 @@ type UrlData = {
|
|||||||
const CHANNELS: { key: NotificationChannel; label: string }[] = [
|
const CHANNELS: { key: NotificationChannel; label: string }[] = [
|
||||||
{ key: "whatsapp", label: "WhatsApp" },
|
{ key: "whatsapp", label: "WhatsApp" },
|
||||||
{ key: "email", label: "Email" },
|
{ key: "email", label: "Email" },
|
||||||
{ key: "system", label: "Sistema" }
|
{ key: "system", label: "Sistema" },
|
||||||
];
|
];
|
||||||
|
|
||||||
type ChannelPreference = "default" | "preferred" | "muted";
|
type ChannelPreference = "default" | "preferred" | "muted";
|
||||||
@@ -30,34 +31,41 @@ export default function NotificationsPage() {
|
|||||||
const oid = data.oid;
|
const oid = data.oid;
|
||||||
const clientId = data.clientId;
|
const clientId = data.clientId;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const store = useNotificationPreferencesStore();
|
const store = useNotificationPreferencesStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
icon: null
|
icon: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + oid,
|
url: "/admin/org/profile/" + oid,
|
||||||
title: "Organización",
|
title: "Organización",
|
||||||
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />
|
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />,
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/" + oid + "/client/" + clientId + "/profile",
|
url: "/admin/org/" + oid + "/client/" + clientId + "/profile",
|
||||||
title: "Cliente",
|
title: "Cliente",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "",
|
url: "",
|
||||||
title: "Notificaciones",
|
title: "Notificaciones",
|
||||||
icon: <NotificationsIcon sx={{ fontSize: "32px", mr: "10px" }} />
|
icon: <NotificationsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, [oid, clientId]);
|
}, [oid, clientId]);
|
||||||
|
|
||||||
const getChannelPreference = (channel: NotificationChannel): ChannelPreference => {
|
const getChannelPreference = (channel: NotificationChannel): ChannelPreference => {
|
||||||
@@ -81,7 +89,7 @@ export default function NotificationsPage() {
|
|||||||
mutedChannels:
|
mutedChannels:
|
||||||
preference === "muted"
|
preference === "muted"
|
||||||
? [...store.formData.mutedChannels.filter((c) => c !== channel), channel]
|
? [...store.formData.mutedChannels.filter((c) => c !== channel), channel]
|
||||||
: store.formData.mutedChannels.filter((c) => c !== channel)
|
: store.formData.mutedChannels.filter((c) => c !== channel),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +99,9 @@ export default function NotificationsPage() {
|
|||||||
|
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<MaterialAlert severity="info" sx={{ marginBottom: "0" }}>
|
<MaterialAlert severity="info" sx={{ marginBottom: "0" }}>
|
||||||
<b>Preferencias del cliente:</b> Configure cómo esta organización debe comunicarse con este cliente. Si deja un canal en estándar, se usará la política general de la organización.
|
<b>Preferencias del cliente:</b> Configure cómo esta organización debe
|
||||||
|
comunicarse con este cliente. Si deja un canal en estándar, se usará la política
|
||||||
|
general de la organización.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
|
|
||||||
<div className={styles.channels}>
|
<div className={styles.channels}>
|
||||||
@@ -102,24 +112,32 @@ export default function NotificationsPage() {
|
|||||||
<div>
|
<div>
|
||||||
<div className={styles.channelTitle}>{channel.label}</div>
|
<div className={styles.channelTitle}>{channel.label}</div>
|
||||||
<div className={styles.channelDescription}>
|
<div className={styles.channelDescription}>
|
||||||
{selectedPreference === "preferred" && "Priorizar este canal para el cliente."}
|
{selectedPreference === "preferred" &&
|
||||||
{selectedPreference === "muted" && "No enviar notificaciones por este canal."}
|
"Priorizar este canal para el cliente."}
|
||||||
{selectedPreference === "default" && "Usar la configuración general de la organización."}
|
{selectedPreference === "muted" &&
|
||||||
|
"No enviar notificaciones por este canal."}
|
||||||
|
{selectedPreference === "default" &&
|
||||||
|
"Usar la configuración general de la organización."}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.options}>
|
<div className={styles.options}>
|
||||||
{[
|
{[
|
||||||
{ key: "default" as ChannelPreference, label: "Estándar" },
|
{ key: "default" as ChannelPreference, label: "Estándar" },
|
||||||
{ key: "preferred" as ChannelPreference, label: "Preferido" },
|
{
|
||||||
{ key: "muted" as ChannelPreference, label: "Silenciado" }
|
key: "preferred" as ChannelPreference,
|
||||||
|
label: "Preferido",
|
||||||
|
},
|
||||||
|
{ key: "muted" as ChannelPreference, label: "Silenciado" },
|
||||||
].map((option) => {
|
].map((option) => {
|
||||||
const isSelected = selectedPreference === option.key;
|
const isSelected = selectedPreference === option.key;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={option.key}
|
key={option.key}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => selectPreference(channel.key, option.key)}
|
onClick={() =>
|
||||||
|
selectPreference(channel.key, option.key)
|
||||||
|
}
|
||||||
className={`${styles.optionButton} ${isSelected ? styles.optionButtonActive : ""}`}
|
className={`${styles.optionButton} ${isSelected ? styles.optionButtonActive : ""}`}
|
||||||
>
|
>
|
||||||
{option.label}
|
{option.label}
|
||||||
|
|||||||
+15
-53
@@ -8,6 +8,7 @@ import { useLocationStore } from "@store/Location.Store";
|
|||||||
import { useNavigation } from "@hooks/goto";
|
import { useNavigation } from "@hooks/goto";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -19,11 +20,14 @@ export default function ClientProfile() {
|
|||||||
const clientId = data.clientId;
|
const clientId = data.clientId;
|
||||||
|
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -33,9 +37,7 @@ export default function ClientProfile() {
|
|||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + oid,
|
url: "/admin/org/profile/" + oid,
|
||||||
title: "Organizacion",
|
title: "Organizacion",
|
||||||
icon: (
|
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />,
|
||||||
<StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
@@ -43,6 +45,10 @@ export default function ClientProfile() {
|
|||||||
title: "Perfil del cliente",
|
title: "Perfil del cliente",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -59,79 +65,35 @@ export default function ClientProfile() {
|
|||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Editar"
|
text="Editar"
|
||||||
icon="/profile-icon.svg"
|
icon="/profile-icon.svg"
|
||||||
onClick={() =>
|
onClick={() => goTo("/admin/org/" + oid + "/client/" + clientId + "/edit")}
|
||||||
goTo(
|
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/edit"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Turnos"
|
text="Turnos"
|
||||||
icon="/profile-icon.svg"
|
icon="/profile-icon.svg"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
goTo(
|
goTo("/admin/org/" + oid + "/client/" + clientId + "/appointments")
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/appointments"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Fusionar Duplicados"
|
text="Fusionar Duplicados"
|
||||||
icon="/client-merge-icon.svg"
|
icon="/client-merge-icon.svg"
|
||||||
onClick={() =>
|
onClick={() => goTo("/admin/org/" + oid + "/client/" + clientId + "/merge")}
|
||||||
goTo(
|
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/merge"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Repeticiones"
|
text="Repeticiones"
|
||||||
icon="/repeat-icon.svg"
|
icon="/repeat-icon.svg"
|
||||||
onClick={() =>
|
onClick={() => goTo("/admin/org/" + oid + "/client/" + clientId + "/repeats")}
|
||||||
goTo(
|
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/repeats"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Cuenta"
|
text="Cuenta"
|
||||||
icon="/account-icon.svg"
|
icon="/account-icon.svg"
|
||||||
onClick={() =>
|
onClick={() => goTo("/admin/org/" + oid + "/client/" + clientId + "/account")}
|
||||||
goTo(
|
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/account"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<ButtonOption
|
<ButtonOption
|
||||||
text="Notificaciones"
|
text="Notificaciones"
|
||||||
icon="/notifications-icon.svg"
|
icon="/notifications-icon.svg"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
goTo(
|
goTo("/admin/org/" + oid + "/client/" + clientId + "/notifications")
|
||||||
"/admin/org/" +
|
|
||||||
oid +
|
|
||||||
"/client/" +
|
|
||||||
clientId +
|
|
||||||
"/notifications"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+9
-1
@@ -17,6 +17,7 @@ import { deleteRepeat, getRepeatsByClient } from "../Client.Service";
|
|||||||
import { DeleteRepeatsParams, FindRepeatsParams, RepeatView } from "@core/Models/Repeats.model";
|
import { DeleteRepeatsParams, FindRepeatsParams, RepeatView } from "@core/Models/Repeats.model";
|
||||||
|
|
||||||
import style from "./repeats.module.css";
|
import style from "./repeats.module.css";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
oid: string;
|
oid: string;
|
||||||
@@ -31,6 +32,7 @@ export default function ClientCreate() {
|
|||||||
const confirm = useConfirmStore();
|
const confirm = useConfirmStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
|
|
||||||
const [repeats, setRepeats] = useState<RepeatView[]>([]);
|
const [repeats, setRepeats] = useState<RepeatView[]>([]);
|
||||||
@@ -52,6 +54,8 @@ export default function ClientCreate() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/clients",
|
url: "/admin/org/profile/" + id + "/clients",
|
||||||
title: "Clientes",
|
title: "Clientes",
|
||||||
@@ -69,6 +73,10 @@ export default function ClientCreate() {
|
|||||||
title: "Repeticiones",
|
title: "Repeticiones",
|
||||||
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ClientsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -162,7 +170,7 @@ export default function ClientCreate() {
|
|||||||
() => {
|
() => {
|
||||||
handleDelete(repeat.id);
|
handleDelete(repeat.id);
|
||||||
},
|
},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import TextObjectFilter from "@components/TextObjectFilter/TextObjectFilter";
|
|||||||
import SelectLocationMap, {
|
import SelectLocationMap, {
|
||||||
LocationCoordinates,
|
LocationCoordinates,
|
||||||
} from "@core/app/components/SelectLocationMap/SelectLocationMap";
|
} from "@core/app/components/SelectLocationMap/SelectLocationMap";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -36,6 +37,7 @@ export default function OrganizationEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -140,7 +142,7 @@ export default function OrganizationEdit() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [localidadesFilterData, setLocalidadesFilterData] = useState<TextObjectFilterResult[]>(
|
const [localidadesFilterData, setLocalidadesFilterData] = useState<TextObjectFilterResult[]>(
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
const [selectedLocalidad, setSelectedLocalidad] = useState<string>("");
|
const [selectedLocalidad, setSelectedLocalidad] = useState<string>("");
|
||||||
|
|
||||||
@@ -188,6 +190,8 @@ export default function OrganizationEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -205,6 +209,10 @@ export default function OrganizationEdit() {
|
|||||||
title: "Ubicación",
|
title: "Ubicación",
|
||||||
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import Button from "@core/app/components/Button/Button";
|
|||||||
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
||||||
import { deleteOrganization } from "./advanced.Service";
|
import { deleteOrganization } from "./advanced.Service";
|
||||||
import { useNavigation } from "@core/app/hooks/goto";
|
import { useNavigation } from "@core/app/hooks/goto";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -23,6 +24,7 @@ export default function OrganizationAdvancedEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -33,6 +35,8 @@ export default function OrganizationAdvancedEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -50,6 +54,10 @@ export default function OrganizationAdvancedEdit() {
|
|||||||
title: "Avanzado",
|
title: "Avanzado",
|
||||||
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const eliminarHandler = () => {
|
const eliminarHandler = () => {
|
||||||
@@ -73,7 +81,7 @@ export default function OrganizationAdvancedEdit() {
|
|||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
alert.showError("La confirmación no es correcta");
|
alert.showError("La confirmación no es correcta");
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { UserAssistanceInfo } from "@core/Models/User.model";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { getAssistanceUserInfo } from "./Assistance.Service";
|
import { getAssistanceUserInfo } from "./Assistance.Service";
|
||||||
import AssistanceIcon from "@mui/icons-material/HeadsetMicOutlined";
|
import AssistanceIcon from "@mui/icons-material/HeadsetMicOutlined";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -23,6 +24,7 @@ export default function CollaboratorsAdd() {
|
|||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const [user, setUser] = useState<UserAssistanceInfo | null>(null);
|
const [user, setUser] = useState<UserAssistanceInfo | null>(null);
|
||||||
const [findEmail, setFindEmail] = useState<string>("");
|
const [findEmail, setFindEmail] = useState<string>("");
|
||||||
@@ -34,6 +36,8 @@ export default function CollaboratorsAdd() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id,
|
url: "/admin/org/profile/" + id,
|
||||||
title: "Organizacion",
|
title: "Organizacion",
|
||||||
@@ -45,6 +49,10 @@ export default function CollaboratorsAdd() {
|
|||||||
title: "Asistencia",
|
title: "Asistencia",
|
||||||
icon: <AssistanceIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <AssistanceIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const findUser = async () => {
|
const findUser = async () => {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { CompanyEmployeesView } from "@models/Collaborators.model";
|
|||||||
import { loadCollaboratorsByCompanyId } from "./Collaborators.Service";
|
import { loadCollaboratorsByCompanyId } from "./Collaborators.Service";
|
||||||
import { useAlert } from "@store/Alert.Store";
|
import { useAlert } from "@store/Alert.Store";
|
||||||
import CollaboratorItem from "@core/app/components/CollaboratorItem/CollaboratorItem";
|
import CollaboratorItem from "@core/app/components/CollaboratorItem/CollaboratorItem";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -19,6 +20,7 @@ export default function OrganizationProfile() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
@@ -31,6 +33,8 @@ export default function OrganizationProfile() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -60,6 +64,10 @@ export default function OrganizationProfile() {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.NEED_ADD);
|
eventHandler.setEventType(EVENT_TYPES.NEED_ADD);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCollaboratorClick = (collaboratorId: string) => {
|
const handleCollaboratorClick = (collaboratorId: string) => {
|
||||||
|
|||||||
+17
-5
@@ -35,6 +35,7 @@ import TextObjectFilterItem from "@core/app/components/TextObjectFilterItem/Text
|
|||||||
import TextObjectFilter from "@core/app/components/TextObjectFilter/TextObjectFilter";
|
import TextObjectFilter from "@core/app/components/TextObjectFilter/TextObjectFilter";
|
||||||
import { useFilterStore } from "@core/Store/Filter.Store";
|
import { useFilterStore } from "@core/Store/Filter.Store";
|
||||||
import filterObjects from "@components/TextObjectFilter/Filter.Service";
|
import filterObjects from "@components/TextObjectFilter/Filter.Service";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -112,6 +113,7 @@ export default function DiscountsEmailGrid() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const oid = data.id;
|
const oid = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -151,7 +153,9 @@ export default function DiscountsEmailGrid() {
|
|||||||
render: (value: DiscountEmailRow) => (
|
render: (value: DiscountEmailRow) => (
|
||||||
<div style={{ paddingBottom: "10px" }}>
|
<div style={{ paddingBottom: "10px" }}>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ paddingLeft: "10px", paddingTop: "10px", fontWeight: "bold" }}>
|
<div
|
||||||
|
style={{ paddingLeft: "10px", paddingTop: "10px", fontWeight: "bold" }}
|
||||||
|
>
|
||||||
{value.discountName + " (" + value.discountCode + ")"}
|
{value.discountName + " (" + value.discountCode + ")"}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ paddingLeft: "10px", paddingTop: "0px", fontWeight: "bold" }}>
|
<div style={{ paddingLeft: "10px", paddingTop: "0px", fontWeight: "bold" }}>
|
||||||
@@ -206,8 +210,10 @@ export default function DiscountsEmailGrid() {
|
|||||||
|
|
||||||
const [pageSize] = useState<number>(
|
const [pageSize] = useState<number>(
|
||||||
parseInt(
|
parseInt(
|
||||||
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE ? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE : "10"
|
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
)
|
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
|
: "10",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const [discounts, setDiscounts] = useState<PaginateDiscountsEmailViewResults>();
|
const [discounts, setDiscounts] = useState<PaginateDiscountsEmailViewResults>();
|
||||||
const discountsRef = useRef(discounts);
|
const discountsRef = useRef(discounts);
|
||||||
@@ -219,6 +225,8 @@ export default function DiscountsEmailGrid() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -238,6 +246,10 @@ export default function DiscountsEmailGrid() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadDiscountsEmail(1, pageSize);
|
loadDiscountsEmail(1, pageSize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -267,7 +279,7 @@ export default function DiscountsEmailGrid() {
|
|||||||
setDiscountId={setDiscountId}
|
setDiscountId={setDiscountId}
|
||||||
filterEmail={filterEmail}
|
filterEmail={filterEmail}
|
||||||
setFilterEmail={setFilterEmail}
|
setFilterEmail={setFilterEmail}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
filter.setOnFilter(() => {
|
filter.setOnFilter(() => {
|
||||||
setSearchByFilters(true);
|
setSearchByFilters(true);
|
||||||
@@ -327,7 +339,7 @@ export default function DiscountsEmailGrid() {
|
|||||||
alert.showError(err.format());
|
alert.showError(err.format());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import turnosXpressTheme from "@core/app/theme/turnosXpress";
|
|||||||
import { ButtonGroup } from "@mui/material";
|
import { ButtonGroup } from "@mui/material";
|
||||||
import ButtonMaterial from "@mui/material/Button";
|
import ButtonMaterial from "@mui/material/Button";
|
||||||
import { useNavigation } from "@core/app/hooks/goto";
|
import { useNavigation } from "@core/app/hooks/goto";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -33,6 +34,7 @@ export default function DiscountsGrid() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const oid = data.id;
|
const oid = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
|
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
@@ -67,7 +69,9 @@ export default function DiscountsGrid() {
|
|||||||
color: "var(--green-darkestX2)",
|
color: "var(--green-darkestX2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value.type === DiscountType.FIXED ? formatPrice(value.value) : value.value + "%"}
|
{value.type === DiscountType.FIXED
|
||||||
|
? formatPrice(value.value)
|
||||||
|
: value.value + "%"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@@ -76,8 +80,10 @@ export default function DiscountsGrid() {
|
|||||||
|
|
||||||
const [pageSize] = useState<number>(
|
const [pageSize] = useState<number>(
|
||||||
parseInt(
|
parseInt(
|
||||||
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE ? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE : "10"
|
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
)
|
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
|
: "10",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const [discounts, setDiscounts] = useState<PaginateDiscountsResults>();
|
const [discounts, setDiscounts] = useState<PaginateDiscountsResults>();
|
||||||
|
|
||||||
@@ -88,6 +94,8 @@ export default function DiscountsGrid() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -107,6 +115,10 @@ export default function DiscountsGrid() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadDiscounts(1, pageSize);
|
loadDiscounts(1, pageSize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadDiscounts = (page: number = 1, pageSize: number = 30) => {
|
const loadDiscounts = (page: number = 1, pageSize: number = 30) => {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import Switch from "@core/app/components/Switch/Switch";
|
|||||||
import { FindTemplatesParams } from "@core/Models/Templates.model";
|
import { FindTemplatesParams } from "@core/Models/Templates.model";
|
||||||
import filterObjects from "@core/app/components/TextObjectFilter/Filter.Service";
|
import filterObjects from "@core/app/components/TextObjectFilter/Filter.Service";
|
||||||
import { CompanyServiceView } from "@models/Service.model";
|
import { CompanyServiceView } from "@models/Service.model";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -47,6 +48,7 @@ export default function OrganizationEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -66,11 +68,12 @@ export default function OrganizationEdit() {
|
|||||||
const [servicesShowPublicScores, setServicesShowPublicScores] = useState(true);
|
const [servicesShowPublicScores, setServicesShowPublicScores] = useState(true);
|
||||||
const [servicesShowPublicOpinions, setServicesShowPublicOpinions] = useState(true);
|
const [servicesShowPublicOpinions, setServicesShowPublicOpinions] = useState(true);
|
||||||
const [originalServicesShowPublicScores, setOriginalServicesShowPublicScores] = useState(true);
|
const [originalServicesShowPublicScores, setOriginalServicesShowPublicScores] = useState(true);
|
||||||
const [originalServicesShowPublicOpinions, setOriginalServicesShowPublicOpinions] = useState(true);
|
const [originalServicesShowPublicOpinions, setOriginalServicesShowPublicOpinions] =
|
||||||
|
useState(true);
|
||||||
const [services, setServices] = useState<CompanyServiceView[]>([]);
|
const [services, setServices] = useState<CompanyServiceView[]>([]);
|
||||||
|
|
||||||
const [orgPublished, setOrgPublished] = useState<COMPANY_PUBLISHED_STATUS | undefined>(
|
const [orgPublished, setOrgPublished] = useState<COMPANY_PUBLISHED_STATUS | undefined>(
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
||||||
@@ -199,6 +202,8 @@ export default function OrganizationEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -218,6 +223,10 @@ export default function OrganizationEdit() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadCategories();
|
loadCategories();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -241,25 +250,33 @@ export default function OrganizationEdit() {
|
|||||||
setCategoryId(organization.categoryId.toString());
|
setCategoryId(organization.categoryId.toString());
|
||||||
setOrgSlug(getSlug(organization.name));
|
setOrgSlug(getSlug(organization.name));
|
||||||
setOrgPublished(organization.published);
|
setOrgPublished(organization.published);
|
||||||
setShowPublicScores(organization.showPublicScores !== undefined ? organization.showPublicScores : true);
|
setShowPublicScores(
|
||||||
setShowPublicOpinions(organization.showPublicOpinions !== undefined ? organization.showPublicOpinions : true);
|
organization.showPublicScores !== undefined
|
||||||
|
? organization.showPublicScores
|
||||||
|
: true,
|
||||||
|
);
|
||||||
|
setShowPublicOpinions(
|
||||||
|
organization.showPublicOpinions !== undefined
|
||||||
|
? organization.showPublicOpinions
|
||||||
|
: true,
|
||||||
|
);
|
||||||
setShowPublicProfessionals(
|
setShowPublicProfessionals(
|
||||||
organization.showPublicProfessionals !== undefined
|
organization.showPublicProfessionals !== undefined
|
||||||
? organization.showPublicProfessionals
|
? organization.showPublicProfessionals
|
||||||
: true
|
: true,
|
||||||
);
|
);
|
||||||
setServices(loadedServices);
|
setServices(loadedServices);
|
||||||
setServicesShowPublicScores(
|
setServicesShowPublicScores(
|
||||||
loadedServices.every((service) => service.showPublicScores !== false)
|
loadedServices.every((service) => service.showPublicScores !== false),
|
||||||
);
|
);
|
||||||
setServicesShowPublicOpinions(
|
setServicesShowPublicOpinions(
|
||||||
loadedServices.every((service) => service.showPublicOpinions !== false)
|
loadedServices.every((service) => service.showPublicOpinions !== false),
|
||||||
);
|
);
|
||||||
setOriginalServicesShowPublicScores(
|
setOriginalServicesShowPublicScores(
|
||||||
loadedServices.every((service) => service.showPublicScores !== false)
|
loadedServices.every((service) => service.showPublicScores !== false),
|
||||||
);
|
);
|
||||||
setOriginalServicesShowPublicOpinions(
|
setOriginalServicesShowPublicOpinions(
|
||||||
loadedServices.every((service) => service.showPublicOpinions !== false)
|
loadedServices.every((service) => service.showPublicOpinions !== false),
|
||||||
);
|
);
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
@@ -287,7 +304,7 @@ export default function OrganizationEdit() {
|
|||||||
confirm.show(
|
confirm.show(
|
||||||
validationPhoneResult.message,
|
validationPhoneResult.message,
|
||||||
() => {},
|
() => {},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
return;
|
return;
|
||||||
@@ -307,7 +324,8 @@ export default function OrganizationEdit() {
|
|||||||
phoneNumber: phone,
|
phoneNumber: phone,
|
||||||
templateWapNotifId: templateWapNotifId === "" ? undefined : templateWapNotifId,
|
templateWapNotifId: templateWapNotifId === "" ? undefined : templateWapNotifId,
|
||||||
templateWapAltaId: templateWapAltaId === "" ? undefined : templateWapAltaId,
|
templateWapAltaId: templateWapAltaId === "" ? undefined : templateWapAltaId,
|
||||||
templateWapCancellationId: templateWapCancellationId === "" ? undefined : templateWapCancellationId,
|
templateWapCancellationId:
|
||||||
|
templateWapCancellationId === "" ? undefined : templateWapCancellationId,
|
||||||
...(canEditPublicVisibilityFlags
|
...(canEditPublicVisibilityFlags
|
||||||
? {
|
? {
|
||||||
showPublicScores,
|
showPublicScores,
|
||||||
@@ -321,31 +339,31 @@ export default function OrganizationEdit() {
|
|||||||
id: Yup.string().required("En este momento no es posible procesar su solicitud."),
|
id: Yup.string().required("En este momento no es posible procesar su solicitud."),
|
||||||
name: Yup.string().required("Debe introducir el nombre de la organización."),
|
name: Yup.string().required("Debe introducir el nombre de la organización."),
|
||||||
description: Yup.string().required(
|
description: Yup.string().required(
|
||||||
"Debe introducir la descripción de la organización."
|
"Debe introducir la descripción de la organización.",
|
||||||
),
|
),
|
||||||
categoryId: Yup.number().required(
|
categoryId: Yup.number().required(
|
||||||
"Debe seleccionar una categoría para la organización."
|
"Debe seleccionar una categoría para la organización.",
|
||||||
),
|
),
|
||||||
phoneAreaCode: Yup.number()
|
phoneAreaCode: Yup.number()
|
||||||
.typeError("Código de área debe ser un número.")
|
.typeError("Código de área debe ser un número.")
|
||||||
.transform((value, originalValue) =>
|
.transform((value, originalValue) =>
|
||||||
originalValue.toString().trim() === "" ? null : value
|
originalValue.toString().trim() === "" ? null : value,
|
||||||
)
|
)
|
||||||
.nullable(),
|
.nullable(),
|
||||||
phoneNumber: Yup.number()
|
phoneNumber: Yup.number()
|
||||||
.typeError("El teléfono debe ser un número.")
|
.typeError("El teléfono debe ser un número.")
|
||||||
.transform((value, originalValue) =>
|
.transform((value, originalValue) =>
|
||||||
originalValue.toString().trim() === "" ? null : value
|
originalValue.toString().trim() === "" ? null : value,
|
||||||
)
|
)
|
||||||
.nullable(),
|
.nullable(),
|
||||||
appointmentAlert: Yup.string().optional().default(""),
|
appointmentAlert: Yup.string().optional().default(""),
|
||||||
sessionUser: Yup.string().required(
|
sessionUser: Yup.string().required(
|
||||||
"Para crear una organización debe iniciar sesión."
|
"Para crear una organización debe iniciar sesión.",
|
||||||
),
|
),
|
||||||
heatMapFraction: Yup.number()
|
heatMapFraction: Yup.number()
|
||||||
.typeError("Fracción de tiempo debe ser un número.")
|
.typeError("Fracción de tiempo debe ser un número.")
|
||||||
.transform((value, originalValue) =>
|
.transform((value, originalValue) =>
|
||||||
originalValue.toString().trim() === "" ? null : value
|
originalValue.toString().trim() === "" ? null : value,
|
||||||
)
|
)
|
||||||
.nullable()
|
.nullable()
|
||||||
.integer("Fracción de tiempo debe ser un número entero en minutos.")
|
.integer("Fracción de tiempo debe ser un número entero en minutos.")
|
||||||
@@ -354,7 +372,7 @@ export default function OrganizationEdit() {
|
|||||||
appointmentTime: Yup.number()
|
appointmentTime: Yup.number()
|
||||||
.typeError("El Plazo Mínimo de Reserva debe ser un número.")
|
.typeError("El Plazo Mínimo de Reserva debe ser un número.")
|
||||||
.transform((value, originalValue) =>
|
.transform((value, originalValue) =>
|
||||||
originalValue.toString().trim() === "" ? null : value
|
originalValue.toString().trim() === "" ? null : value,
|
||||||
)
|
)
|
||||||
.nullable()
|
.nullable()
|
||||||
.integer("El Plazo Mínimo de Reserva debe ser un número entero en horas.")
|
.integer("El Plazo Mínimo de Reserva debe ser un número entero en horas.")
|
||||||
@@ -362,7 +380,7 @@ export default function OrganizationEdit() {
|
|||||||
cancellationTime: Yup.number()
|
cancellationTime: Yup.number()
|
||||||
.typeError("El Plazo Mínimo de Cancelación debe ser un número.")
|
.typeError("El Plazo Mínimo de Cancelación debe ser un número.")
|
||||||
.transform((value, originalValue) =>
|
.transform((value, originalValue) =>
|
||||||
originalValue.toString().trim() === "" ? null : value
|
originalValue.toString().trim() === "" ? null : value,
|
||||||
)
|
)
|
||||||
.nullable()
|
.nullable()
|
||||||
.integer("El Plazo Mínimo de Cancelación debe ser un número entero en horas.")
|
.integer("El Plazo Mínimo de Cancelación debe ser un número entero en horas.")
|
||||||
@@ -386,7 +404,8 @@ export default function OrganizationEdit() {
|
|||||||
originalServicesShowPublicOpinions !== servicesShowPublicOpinions;
|
originalServicesShowPublicOpinions !== servicesShowPublicOpinions;
|
||||||
const changedServices =
|
const changedServices =
|
||||||
canEditPublicVisibilityFlags &&
|
canEditPublicVisibilityFlags &&
|
||||||
(servicesShowPublicScoresChanged || servicesShowPublicOpinionsChanged)
|
(servicesShowPublicScoresChanged ||
|
||||||
|
servicesShowPublicOpinionsChanged)
|
||||||
? services
|
? services
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
@@ -414,8 +433,8 @@ export default function OrganizationEdit() {
|
|||||||
: service.showPublicOpinions !== undefined
|
: service.showPublicOpinions !== undefined
|
||||||
? service.showPublicOpinions
|
? service.showPublicOpinions
|
||||||
: true,
|
: true,
|
||||||
})
|
}),
|
||||||
)
|
),
|
||||||
).then(() => {
|
).then(() => {
|
||||||
const updatedServices = services.map((service) => ({
|
const updatedServices = services.map((service) => ({
|
||||||
...service,
|
...service,
|
||||||
@@ -434,7 +453,9 @@ export default function OrganizationEdit() {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error: ApiError | Error) => {
|
.catch((error: ApiError | Error) => {
|
||||||
alert.showError(error instanceof ApiError ? error.format() : error.message);
|
alert.showError(
|
||||||
|
error instanceof ApiError ? error.format() : error.message,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -453,7 +474,7 @@ export default function OrganizationEdit() {
|
|||||||
id: category.id.toString(),
|
id: category.id.toString(),
|
||||||
name: category.name,
|
name: category.name,
|
||||||
description: category.description,
|
description: category.description,
|
||||||
}))
|
})),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -533,7 +554,7 @@ export default function OrganizationEdit() {
|
|||||||
setOrgPublished(
|
setOrgPublished(
|
||||||
checked
|
checked
|
||||||
? COMPANY_PUBLISHED_STATUS.PUBLISHED
|
? COMPANY_PUBLISHED_STATUS.PUBLISHED
|
||||||
: COMPANY_PUBLISHED_STATUS.PRIVATE
|
: COMPANY_PUBLISHED_STATUS.PRIVATE,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -581,15 +602,23 @@ export default function OrganizationEdit() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones, opiniones y profesionales en el perfil público y las páginas de reserva. Disponible para planes pagos.
|
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones, opiniones y
|
||||||
|
profesionales en el perfil público y las páginas de reserva. Disponible para planes
|
||||||
|
pagos.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
{!canEditPublicVisibilityFlags && (
|
{!canEditPublicVisibilityFlags && (
|
||||||
<MaterialAlert severity="warning" sx={{ marginTop: "10px" }}>
|
<MaterialAlert severity="warning" sx={{ marginTop: "10px" }}>
|
||||||
Para modificar las opciones de visibilidad pública de opiniones, puntuaciones y profesionales de esta organización y sus servicios, el propietario de la organización necesita un plan pago.
|
Para modificar las opciones de visibilidad pública de opiniones, puntuaciones y
|
||||||
|
profesionales de esta organización y sus servicios, el propietario de la
|
||||||
|
organización necesita un plan pago.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
)}
|
)}
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}>
|
<div
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={showPublicScores}
|
checked={showPublicScores}
|
||||||
disabled={!canEditPublicVisibilityFlags}
|
disabled={!canEditPublicVisibilityFlags}
|
||||||
@@ -600,7 +629,9 @@ export default function OrganizationEdit() {
|
|||||||
/>
|
/>
|
||||||
Mostrar puntuaciones públicas
|
Mostrar puntuaciones públicas
|
||||||
</label>
|
</label>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
<label
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={showPublicOpinions}
|
checked={showPublicOpinions}
|
||||||
disabled={!canEditPublicVisibilityFlags}
|
disabled={!canEditPublicVisibilityFlags}
|
||||||
@@ -611,7 +642,9 @@ export default function OrganizationEdit() {
|
|||||||
/>
|
/>
|
||||||
Mostrar opiniones públicas
|
Mostrar opiniones públicas
|
||||||
</label>
|
</label>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
<label
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={showPublicProfessionals}
|
checked={showPublicProfessionals}
|
||||||
disabled={!canEditPublicVisibilityFlags}
|
disabled={!canEditPublicVisibilityFlags}
|
||||||
@@ -632,7 +665,9 @@ export default function OrganizationEdit() {
|
|||||||
{services.length > 0 && (
|
{services.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
<b>Visibilidad pública de servicios:</b> Configurá si se muestran puntuaciones y opiniones en todos los servicios. Disponible para planes pagos.
|
<b>Visibilidad pública de servicios:</b> Configurá si se muestran
|
||||||
|
puntuaciones y opiniones en todos los servicios. Disponible para planes
|
||||||
|
pagos.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -642,7 +677,14 @@ export default function OrganizationEdit() {
|
|||||||
marginTop: "10px",
|
marginTop: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
<label
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={servicesShowPublicScores}
|
checked={servicesShowPublicScores}
|
||||||
disabled={!canEditPublicVisibilityFlags}
|
disabled={!canEditPublicVisibilityFlags}
|
||||||
@@ -653,7 +695,14 @@ export default function OrganizationEdit() {
|
|||||||
/>
|
/>
|
||||||
Mostrar puntuaciones públicas de los servicios
|
Mostrar puntuaciones públicas de los servicios
|
||||||
</label>
|
</label>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
<label
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={servicesShowPublicOpinions}
|
checked={servicesShowPublicOpinions}
|
||||||
disabled={!canEditPublicVisibilityFlags}
|
disabled={!canEditPublicVisibilityFlags}
|
||||||
@@ -666,7 +715,8 @@ export default function OrganizationEdit() {
|
|||||||
</label>
|
</label>
|
||||||
{!canEditPublicVisibilityFlags && (
|
{!canEditPublicVisibilityFlags && (
|
||||||
<span style={{ color: "var(--gray-darkest)", fontSize: "13px" }}>
|
<span style={{ color: "var(--gray-darkest)", fontSize: "13px" }}>
|
||||||
Para cambiar la visibilidad pública de los servicios necesitás un plan pago.
|
Para cambiar la visibilidad pública de los servicios necesitás un
|
||||||
|
plan pago.
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
OrganizationFiscalProfileTaxCondition,
|
OrganizationFiscalProfileTaxCondition,
|
||||||
upsertOrganizationFiscalProfile,
|
upsertOrganizationFiscalProfile,
|
||||||
} from "./Fiscal.Service";
|
} from "./Fiscal.Service";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -33,13 +34,15 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
|
|
||||||
const [cuit, setCuit] = useState("");
|
const [cuit, setCuit] = useState("");
|
||||||
const [legalName, setLegalName] = useState("");
|
const [legalName, setLegalName] = useState("");
|
||||||
const [taxCondition, setTaxCondition] = useState<OrganizationFiscalProfileTaxCondition>("MONOTRIBUTO");
|
const [taxCondition, setTaxCondition] =
|
||||||
|
useState<OrganizationFiscalProfileTaxCondition>("MONOTRIBUTO");
|
||||||
const [pointOfSale, setPointOfSale] = useState("1");
|
const [pointOfSale, setPointOfSale] = useState("1");
|
||||||
const [activityCode, setActivityCode] = useState("");
|
const [activityCode, setActivityCode] = useState("");
|
||||||
const [activityDescription, setActivityDescription] = useState("");
|
const [activityDescription, setActivityDescription] = useState("");
|
||||||
@@ -80,6 +83,8 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.clear();
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -97,6 +102,10 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
title: "Datos fiscales",
|
title: "Datos fiscales",
|
||||||
icon: <ReceiptLongOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <ReceiptLongOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -118,7 +127,9 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
setLegalName(profile.legalName || "");
|
setLegalName(profile.legalName || "");
|
||||||
setTaxCondition(profile.taxCondition || "MONOTRIBUTO");
|
setTaxCondition(profile.taxCondition || "MONOTRIBUTO");
|
||||||
setPointOfSale(profile.pointOfSale ? String(profile.pointOfSale) : "1");
|
setPointOfSale(profile.pointOfSale ? String(profile.pointOfSale) : "1");
|
||||||
const profileActivity = activities.find((activity) => activity.id === profile.activityCode);
|
const profileActivity = activities.find(
|
||||||
|
(activity) => activity.id === profile.activityCode,
|
||||||
|
);
|
||||||
setActivityCode(profile.activityCode || "");
|
setActivityCode(profile.activityCode || "");
|
||||||
setActivityDescription(profile.activityDescription || profileActivity?.name || "");
|
setActivityDescription(profile.activityDescription || profileActivity?.name || "");
|
||||||
})
|
})
|
||||||
@@ -152,7 +163,10 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activityCode.trim() && !arcaActivities.some((activity) => activity.id === activityCode.trim())) {
|
if (
|
||||||
|
activityCode.trim() &&
|
||||||
|
!arcaActivities.some((activity) => activity.id === activityCode.trim())
|
||||||
|
) {
|
||||||
alert.showError("Seleccioná una actividad ARCA/CLAE válida.");
|
alert.showError("Seleccioná una actividad ARCA/CLAE válida.");
|
||||||
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
return;
|
return;
|
||||||
@@ -160,7 +174,9 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
|
|
||||||
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
||||||
|
|
||||||
const selectedActivity = arcaActivities.find((activity) => activity.id === activityCode.trim());
|
const selectedActivity = arcaActivities.find(
|
||||||
|
(activity) => activity.id === activityCode.trim(),
|
||||||
|
);
|
||||||
|
|
||||||
upsertOrganizationFiscalProfile({
|
upsertOrganizationFiscalProfile({
|
||||||
companyId: id,
|
companyId: id,
|
||||||
@@ -173,7 +189,9 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
sessionUser: SessionInfo.userId,
|
sessionUser: SessionInfo.userId,
|
||||||
})
|
})
|
||||||
.then((profile) => {
|
.then((profile) => {
|
||||||
const savedActivity = arcaActivities.find((activity) => activity.id === profile.activityCode);
|
const savedActivity = arcaActivities.find(
|
||||||
|
(activity) => activity.id === profile.activityCode,
|
||||||
|
);
|
||||||
setActivityCode(profile.activityCode || "");
|
setActivityCode(profile.activityCode || "");
|
||||||
setActivityDescription(profile.activityDescription || savedActivity?.name || "");
|
setActivityDescription(profile.activityDescription || savedActivity?.name || "");
|
||||||
alert.showSuccess("Datos fiscales actualizados.");
|
alert.showSuccess("Datos fiscales actualizados.");
|
||||||
@@ -198,7 +216,8 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
<div>
|
<div>
|
||||||
<h2>Configuración fiscal</h2>
|
<h2>Configuración fiscal</h2>
|
||||||
<p>
|
<p>
|
||||||
Estos datos se usan para emitir Factura C desde los movimientos de caja y para precargar el asistente ARCA.
|
Estos datos se usan para emitir Factura C desde los movimientos de
|
||||||
|
caja y para precargar el asistente ARCA.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -206,32 +225,32 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
<section className={style.formSection}>
|
<section className={style.formSection}>
|
||||||
<h3>Datos del emisor</h3>
|
<h3>Datos del emisor</h3>
|
||||||
<Grid2 container spacing={2}>
|
<Grid2 container spacing={2}>
|
||||||
<Grid2 size={{ xs: 12, sm: 6 }}>
|
<Grid2 size={{ xs: 12, sm: 6 }}>
|
||||||
<Textbox
|
<Textbox
|
||||||
name="cuit"
|
name="cuit"
|
||||||
placeholder="CUIT"
|
placeholder="CUIT"
|
||||||
type="text"
|
type="text"
|
||||||
value={cuit}
|
value={cuit}
|
||||||
width="100%"
|
width="100%"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setCuit(event.target.value.replace(/\D/g, ""));
|
setCuit(event.target.value.replace(/\D/g, ""));
|
||||||
markNeedsSave();
|
markNeedsSave();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
<Grid2 size={{ xs: 12, sm: 6 }}>
|
<Grid2 size={{ xs: 12, sm: 6 }}>
|
||||||
<Textbox
|
<Textbox
|
||||||
name="legalName"
|
name="legalName"
|
||||||
placeholder="Razón social"
|
placeholder="Razón social"
|
||||||
type="text"
|
type="text"
|
||||||
value={legalName}
|
value={legalName}
|
||||||
width="100%"
|
width="100%"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setLegalName(event.target.value);
|
setLegalName(event.target.value);
|
||||||
markNeedsSave();
|
markNeedsSave();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -240,7 +259,11 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
<h3>Condición fiscal</h3>
|
<h3>Condición fiscal</h3>
|
||||||
<p>Seleccioná la condición declarada para esta organización.</p>
|
<p>Seleccioná la condición declarada para esta organización.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.optionGroup} role="radiogroup" aria-label="Condición fiscal">
|
<div
|
||||||
|
className={style.optionGroup}
|
||||||
|
role="radiogroup"
|
||||||
|
aria-label="Condición fiscal"
|
||||||
|
>
|
||||||
{fiscalConditionOptions.map((option) => {
|
{fiscalConditionOptions.map((option) => {
|
||||||
const selected = taxCondition === option.id;
|
const selected = taxCondition === option.id;
|
||||||
|
|
||||||
@@ -256,7 +279,9 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
aria-pressed={selected}
|
aria-pressed={selected}
|
||||||
>
|
>
|
||||||
<span className={style.optionTitle}>{option.title}</span>
|
<span className={style.optionTitle}>{option.title}</span>
|
||||||
<span className={style.optionDescription}>{option.description}</span>
|
<span className={style.optionDescription}>
|
||||||
|
{option.description}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -266,19 +291,19 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
<section className={style.formSection}>
|
<section className={style.formSection}>
|
||||||
<h3>Facturación ARCA</h3>
|
<h3>Facturación ARCA</h3>
|
||||||
<Grid2 container spacing={2}>
|
<Grid2 container spacing={2}>
|
||||||
<Grid2 size={{ xs: 12, sm: 6 }}>
|
<Grid2 size={{ xs: 12, sm: 6 }}>
|
||||||
<Textbox
|
<Textbox
|
||||||
name="pointOfSale"
|
name="pointOfSale"
|
||||||
placeholder="Punto de venta"
|
placeholder="Punto de venta"
|
||||||
type="text"
|
type="text"
|
||||||
value={pointOfSale}
|
value={pointOfSale}
|
||||||
width="100%"
|
width="100%"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setPointOfSale(event.target.value.replace(/\D/g, ""));
|
setPointOfSale(event.target.value.replace(/\D/g, ""));
|
||||||
markNeedsSave();
|
markNeedsSave();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
|
|
||||||
{fiscalDataLoaded && (
|
{fiscalDataLoaded && (
|
||||||
@@ -290,7 +315,7 @@ export default function OrganizationFiscalProfileEdit() {
|
|||||||
selectedId={activityCode}
|
selectedId={activityCode}
|
||||||
onChange={(selectedActivityCode) => {
|
onChange={(selectedActivityCode) => {
|
||||||
const selectedActivity = arcaActivities.find(
|
const selectedActivity = arcaActivities.find(
|
||||||
(activity) => activity.id === selectedActivityCode
|
(activity) => activity.id === selectedActivityCode,
|
||||||
);
|
);
|
||||||
|
|
||||||
setActivityCode(selectedActivity?.id || "");
|
setActivityCode(selectedActivity?.id || "");
|
||||||
|
|||||||
+64
-22
@@ -13,6 +13,7 @@ import StorefrontOutlinedIcon from "@mui/icons-material/StorefrontOutlined";
|
|||||||
import NotificationsIcon from "@mui/icons-material/NotificationsOutlined";
|
import NotificationsIcon from "@mui/icons-material/NotificationsOutlined";
|
||||||
import MaterialAlert from "@mui/material/Alert";
|
import MaterialAlert from "@mui/material/Alert";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -21,7 +22,7 @@ type UrlData = {
|
|||||||
const CHANNELS: { key: NotificationChannel; label: string }[] = [
|
const CHANNELS: { key: NotificationChannel; label: string }[] = [
|
||||||
{ key: "whatsapp", label: "WhatsApp" },
|
{ key: "whatsapp", label: "WhatsApp" },
|
||||||
{ key: "email", label: "Email" },
|
{ key: "email", label: "Email" },
|
||||||
{ key: "system", label: "Sistema" }
|
{ key: "system", label: "Sistema" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const REMINDER_PRESETS: { minutes: number; label: string }[] = [
|
const REMINDER_PRESETS: { minutes: number; label: string }[] = [
|
||||||
@@ -30,36 +31,43 @@ const REMINDER_PRESETS: { minutes: number; label: string }[] = [
|
|||||||
{ minutes: 360, label: "6 horas antes" },
|
{ minutes: 360, label: "6 horas antes" },
|
||||||
{ minutes: 720, label: "12 horas antes" },
|
{ minutes: 720, label: "12 horas antes" },
|
||||||
{ minutes: 1440, label: "1 día antes" },
|
{ minutes: 1440, label: "1 día antes" },
|
||||||
{ minutes: 2880, label: "2 días antes" }
|
{ minutes: 2880, label: "2 días antes" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function NotificationsPage() {
|
export default function NotificationsPage() {
|
||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const store = useNotificationPreferencesStore();
|
const store = useNotificationPreferencesStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
icon: null
|
icon: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id,
|
url: "/admin/org/profile/" + id,
|
||||||
title: "Perfil",
|
title: "Perfil",
|
||||||
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />
|
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />,
|
||||||
});
|
});
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org/profile/" + id + "/notifications",
|
url: "/admin/org/profile/" + id + "/notifications",
|
||||||
title: "Notificaciones",
|
title: "Notificaciones",
|
||||||
icon: <NotificationsIcon sx={{ fontSize: "32px", mr: "10px" }} />
|
icon: <NotificationsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
const toggleChannel = (channel: NotificationChannel) => {
|
const toggleChannel = (channel: NotificationChannel) => {
|
||||||
@@ -73,18 +81,22 @@ export default function NotificationsPage() {
|
|||||||
const updateQuietHours = (field: "from" | "to", value: string) => {
|
const updateQuietHours = (field: "from" | "to", value: string) => {
|
||||||
const current = store.formData.quietHours || { from: "00:00", to: "00:00" };
|
const current = store.formData.quietHours || { from: "00:00", to: "00:00" };
|
||||||
store.updateFormData({
|
store.updateFormData({
|
||||||
quietHours: { ...current, [field]: value }
|
quietHours: { ...current, [field]: value },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const quietHourValue = (value: string | undefined, fallback: string) => {
|
const quietHourValue = (value: string | undefined, fallback: string) => {
|
||||||
const [hour, minute] = (value || fallback).split(":").map(Number);
|
const [hour, minute] = (value || fallback).split(":").map(Number);
|
||||||
return dayjs(new Date()).hour(hour).minute(minute || 0).second(0).millisecond(0);
|
return dayjs(new Date())
|
||||||
|
.hour(hour)
|
||||||
|
.minute(minute || 0)
|
||||||
|
.second(0)
|
||||||
|
.millisecond(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleQuietHours = () => {
|
const toggleQuietHours = () => {
|
||||||
store.updateFormData({
|
store.updateFormData({
|
||||||
quietHours: store.formData.quietHours ? null : { from: "22:00", to: "08:00" }
|
quietHours: store.formData.quietHours ? null : { from: "22:00", to: "08:00" },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,7 +107,10 @@ export default function NotificationsPage() {
|
|||||||
store.updateFormData({ reminderRules: updated });
|
store.updateFormData({ reminderRules: updated });
|
||||||
} else {
|
} else {
|
||||||
store.updateFormData({
|
store.updateFormData({
|
||||||
reminderRules: [...store.formData.reminderRules, { offset: minutes, enabled: true }]
|
reminderRules: [
|
||||||
|
...store.formData.reminderRules,
|
||||||
|
{ offset: minutes, enabled: true },
|
||||||
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -107,10 +122,18 @@ export default function NotificationsPage() {
|
|||||||
<div style={{ marginTop: "20px" }}>
|
<div style={{ marginTop: "20px" }}>
|
||||||
{/* Channel Toggles Section */}
|
{/* Channel Toggles Section */}
|
||||||
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
||||||
<b>Canales de notificación:</b> Seleccione los canales por los cuales se enviarán las notificaciones automáticas.
|
<b>Canales de notificación:</b> Seleccione los canales por los cuales se
|
||||||
|
enviarán las notificaciones automáticas.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
|
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "8px", marginBottom: "30px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "8px",
|
||||||
|
marginBottom: "30px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{CHANNELS.map((channel) => (
|
{CHANNELS.map((channel) => (
|
||||||
<div
|
<div
|
||||||
key={channel.key}
|
key={channel.key}
|
||||||
@@ -121,10 +144,12 @@ export default function NotificationsPage() {
|
|||||||
padding: "12px 16px",
|
padding: "12px 16px",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
border: "1px solid var(--border-color)",
|
border: "1px solid var(--border-color)",
|
||||||
backgroundColor: "var(--bg-primary)"
|
backgroundColor: "var(--bg-primary)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ color: "var(--text-primary)", fontWeight: "500" }}>{channel.label}</span>
|
<span style={{ color: "var(--text-primary)", fontWeight: "500" }}>
|
||||||
|
{channel.label}
|
||||||
|
</span>
|
||||||
<Switch
|
<Switch
|
||||||
checked={store.formData.defaultChannels.includes(channel.key)}
|
checked={store.formData.defaultChannels.includes(channel.key)}
|
||||||
onChange={() => toggleChannel(channel.key)}
|
onChange={() => toggleChannel(channel.key)}
|
||||||
@@ -135,7 +160,8 @@ export default function NotificationsPage() {
|
|||||||
|
|
||||||
{/* Quiet Hours Section */}
|
{/* Quiet Hours Section */}
|
||||||
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
||||||
<b>Horario silencioso:</b> Las notificaciones no se enviarán durante este rango horario.
|
<b>Horario silencioso:</b> Las notificaciones no se enviarán durante este rango
|
||||||
|
horario.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -147,7 +173,7 @@ export default function NotificationsPage() {
|
|||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
border: "1px solid var(--border-color)",
|
border: "1px solid var(--border-color)",
|
||||||
backgroundColor: "var(--bg-primary)",
|
backgroundColor: "var(--bg-primary)",
|
||||||
marginBottom: "16px"
|
marginBottom: "16px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ color: "var(--text-primary)", fontWeight: "500" }}>
|
<span style={{ color: "var(--text-primary)", fontWeight: "500" }}>
|
||||||
@@ -160,13 +186,22 @@ export default function NotificationsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{store.formData.quietHours && (
|
{store.formData.quietHours && (
|
||||||
<div style={{ display: "flex", gap: "16px", alignItems: "flex-end", marginBottom: "30px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "16px",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
marginBottom: "30px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<TextTime
|
<TextTime
|
||||||
placeholder="Desde"
|
placeholder="Desde"
|
||||||
width="100%"
|
width="100%"
|
||||||
value={quietHourValue(store.formData.quietHours.from, "22:00")}
|
value={quietHourValue(store.formData.quietHours.from, "22:00")}
|
||||||
onChange={(value) => updateQuietHours("from", value.format("HH:mm"))}
|
onChange={(value) =>
|
||||||
|
updateQuietHours("from", value.format("HH:mm"))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
@@ -182,12 +217,15 @@ export default function NotificationsPage() {
|
|||||||
|
|
||||||
{/* Reminder Rules Section */}
|
{/* Reminder Rules Section */}
|
||||||
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginBottom: "20px" }}>
|
||||||
<b>Reglas de recordatorio:</b> Active los momentos en los que desea enviar recordatorios antes del turno.
|
<b>Reglas de recordatorio:</b> Active los momentos en los que desea enviar
|
||||||
|
recordatorios antes del turno.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
|
|
||||||
<div style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
|
<div style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
|
||||||
{REMINDER_PRESETS.map((preset) => {
|
{REMINDER_PRESETS.map((preset) => {
|
||||||
const isActive = store.formData.reminderRules.some((r) => r.offset === preset.minutes);
|
const isActive = store.formData.reminderRules.some(
|
||||||
|
(r) => r.offset === preset.minutes,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={preset.minutes}
|
key={preset.minutes}
|
||||||
@@ -198,11 +236,15 @@ export default function NotificationsPage() {
|
|||||||
padding: "10px 16px",
|
padding: "10px 16px",
|
||||||
borderRadius: "999px",
|
borderRadius: "999px",
|
||||||
border: `1px solid ${isActive ? "var(--primary-color)" : "var(--border-color)"}`,
|
border: `1px solid ${isActive ? "var(--primary-color)" : "var(--border-color)"}`,
|
||||||
backgroundColor: isActive ? "rgba(25, 118, 210, 0.12)" : "var(--bg-primary)",
|
backgroundColor: isActive
|
||||||
color: isActive ? "var(--primary-color)" : "var(--text-secondary)",
|
? "rgba(25, 118, 210, 0.12)"
|
||||||
|
: "var(--bg-primary)",
|
||||||
|
color: isActive
|
||||||
|
? "var(--primary-color)"
|
||||||
|
: "var(--text-secondary)",
|
||||||
fontWeight: isActive ? "600" : "500",
|
fontWeight: isActive ? "600" : "500",
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
transition: "all 0.2s ease"
|
transition: "all 0.2s ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{preset.label}
|
{preset.label}
|
||||||
|
|||||||
+304
-109
@@ -248,7 +248,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
const [dialogPayVisible, setDialogPayVisible] = useState<boolean>(false);
|
const [dialogPayVisible, setDialogPayVisible] = useState<boolean>(false);
|
||||||
const [dialogPayOneVisible, setDialogPayOneVisible] = useState<boolean>(false);
|
const [dialogPayOneVisible, setDialogPayOneVisible] = useState<boolean>(false);
|
||||||
const [createPaymentData, setCreatePaymentData] = useState<PaginatePaymentsView | undefined>(
|
const [createPaymentData, setCreatePaymentData] = useState<PaginatePaymentsView | undefined>(
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [paymentMethodFilterContent] = useState<TextObjectModalContent>({
|
const [paymentMethodFilterContent] = useState<TextObjectModalContent>({
|
||||||
@@ -284,7 +284,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
TextObjectFilterResult[]
|
TextObjectFilterResult[]
|
||||||
>([]);
|
>([]);
|
||||||
const [paymentMethodId, setPaymentMethodId] = useState<CLIENT_ACCOUNT_PAYMENT_METHODS>(
|
const [paymentMethodId, setPaymentMethodId] = useState<CLIENT_ACCOUNT_PAYMENT_METHODS>(
|
||||||
CLIENT_ACCOUNT_PAYMENT_METHODS.CASH
|
CLIENT_ACCOUNT_PAYMENT_METHODS.CASH,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -326,7 +326,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
TextObjectFilterResult[]
|
TextObjectFilterResult[]
|
||||||
>([]);
|
>([]);
|
||||||
const [paymentProcessDateId, setPaymentProcessDateId] = useState<PAYMENT_PROCCESS_DATE>(
|
const [paymentProcessDateId, setPaymentProcessDateId] = useState<PAYMENT_PROCCESS_DATE>(
|
||||||
PAYMENT_PROCCESS_DATE.NOW
|
PAYMENT_PROCCESS_DATE.NOW,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -356,7 +356,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
id: category.id.toString(),
|
id: category.id.toString(),
|
||||||
name: category.name,
|
name: category.name,
|
||||||
description: category.description,
|
description: category.description,
|
||||||
}))
|
})),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
const [clientIds, setClientIds] = useState<string[]>([]);
|
const [clientIds, setClientIds] = useState<string[]>([]);
|
||||||
|
|
||||||
const [collaboratorFilterData, setCollaboratorFilterData] = useState<TextObjectFilterResult[]>(
|
const [collaboratorFilterData, setCollaboratorFilterData] = useState<TextObjectFilterResult[]>(
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
const [collaboratorId, setCollaboratorId] = useState<string>("");
|
const [collaboratorId, setCollaboratorId] = useState<string>("");
|
||||||
|
|
||||||
@@ -484,8 +484,8 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
parseInt(
|
parseInt(
|
||||||
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
: "10"
|
: "10",
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
const [payments, setPayments] = useState<PaginateNotPayedAppointmentsResult>();
|
const [payments, setPayments] = useState<PaginateNotPayedAppointmentsResult>();
|
||||||
const paymentsRef = useRef(payments);
|
const paymentsRef = useRef(payments);
|
||||||
@@ -595,7 +595,6 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const generarReporte = async () => {
|
const generarReporte = async () => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
||||||
try {
|
try {
|
||||||
@@ -625,27 +624,27 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
reader.onloadend = () => resolve(reader.result as string);
|
reader.onloadend = () => resolve(reader.result as string);
|
||||||
reader.readAsDataURL(blob);
|
reader.readAsDataURL(blob);
|
||||||
});
|
});
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
const tableBody: any[] = [
|
const tableBody: any[] = [
|
||||||
[
|
[
|
||||||
{ text: "Cliente", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
{ text: "Cliente", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
{ text: "Datos del Turno", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
{ text: "Datos del Turno", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
{ text: "Monto", bold: true, color: "#333333", fillColor: "#f5f5f5" }
|
{ text: "Monto", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
report.items.forEach(item => {
|
report.items.forEach((item) => {
|
||||||
tableBody.push([
|
tableBody.push([
|
||||||
item.clientName || "-",
|
item.clientName || "-",
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: `${item.serviceName || "-"}\n`, bold: true, fontSize: 11 },
|
{ text: `${item.serviceName || "-"}\n`, bold: true, fontSize: 11 },
|
||||||
`Prof: ${item.employeeName || "-"}\nFecha: ${dayjs(item.appointmentDate).format("DD/MM/YYYY HH:mm")} hs`
|
`Prof: ${item.employeeName || "-"}\nFecha: ${dayjs(item.appointmentDate).format("DD/MM/YYYY HH:mm")} hs`,
|
||||||
],
|
],
|
||||||
fontSize: 10
|
fontSize: 10,
|
||||||
},
|
},
|
||||||
{ text: "$" + item.price.toLocaleString("es-AR"), alignment: "right" }
|
{ text: "$" + item.price.toLocaleString("es-AR"), alignment: "right" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -653,52 +652,81 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
tableBody.push([
|
tableBody.push([
|
||||||
{ text: "TOTAL ADEUDADO", bold: true, colSpan: 2, alignment: "right" },
|
{ text: "TOTAL ADEUDADO", bold: true, colSpan: 2, alignment: "right" },
|
||||||
{},
|
{},
|
||||||
{ text: "$" + report.totalAmount.toLocaleString("es-AR"), bold: true, alignment: "right" }
|
{
|
||||||
|
text: "$" + report.totalAmount.toLocaleString("es-AR"),
|
||||||
|
bold: true,
|
||||||
|
alignment: "right",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const docDefinition: unknown = {
|
const docDefinition: unknown = {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
columns: [
|
columns: [
|
||||||
{ text: "Reporte de Turnos Adeudados", fontSize: 18, bold: true, margin: [0, 0, 0, 10], width: '*' },
|
{
|
||||||
...(logoDataUrl ? [{ image: logoDataUrl, width: 45, margin: [0, 0, 0, 10], alignment: 'right' }] : [])
|
text: "Reporte de Turnos Adeudados",
|
||||||
]
|
fontSize: 18,
|
||||||
|
bold: true,
|
||||||
|
margin: [0, 0, 0, 10],
|
||||||
|
width: "*",
|
||||||
|
},
|
||||||
|
...(logoDataUrl
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
image: logoDataUrl,
|
||||||
|
width: 45,
|
||||||
|
margin: [0, 0, 0, 10],
|
||||||
|
alignment: "right",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{ text: `Filtros aplicados:`, bold: true, margin: [0, 0, 0, 5] },
|
{ text: `Filtros aplicados:`, bold: true, margin: [0, 0, 0, 5] },
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: "Clientes Seleccionados: ", bold: true },
|
{ text: "Clientes Seleccionados: ", bold: true },
|
||||||
`${clientIds.length > 0 ? clientIds.length : "Todos"}`
|
`${clientIds.length > 0 ? clientIds.length : "Todos"}`,
|
||||||
],
|
],
|
||||||
margin: [0, 0, 0, 2]
|
margin: [0, 0, 0, 2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: "Período: ", bold: true },
|
{ text: "Período: ", bold: true },
|
||||||
`${dateFrom ? dateFrom.format("DD/MM/YYYY") : "Inicio"} al ${dateTo ? dateTo.format("DD/MM/YYYY") : "Fin"}`
|
`${dateFrom ? dateFrom.format("DD/MM/YYYY") : "Inicio"} al ${dateTo ? dateTo.format("DD/MM/YYYY") : "Fin"}`,
|
||||||
],
|
],
|
||||||
margin: [0, 0, 0, 20]
|
margin: [0, 0, 0, 20],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
table: {
|
table: {
|
||||||
headerRows: 1,
|
headerRows: 1,
|
||||||
widths: [120, "*", "auto"],
|
widths: [120, "*", "auto"],
|
||||||
body: tableBody
|
body: tableBody,
|
||||||
},
|
},
|
||||||
layout: "lightHorizontalLines"
|
layout: "lightHorizontalLines",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((window as unknown as { Android: any }).Android && (window as unknown as { Android: any }).Android.savePdf) {
|
if (
|
||||||
|
(window as unknown as { Android: any }).Android &&
|
||||||
|
(window as unknown as { Android: any }).Android.savePdf
|
||||||
|
) {
|
||||||
pdfMake.createPdf(docDefinition as any).getBase64((data: any) => {
|
pdfMake.createPdf(docDefinition as any).getBase64((data: any) => {
|
||||||
(window as unknown as { Android: any }).Android?.savePdf(data, `reporte-adeudados.pdf`);
|
(window as unknown as { Android: any }).Android?.savePdf(
|
||||||
|
data,
|
||||||
|
`reporte-adeudados.pdf`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pdfMake.createPdf(docDefinition as any).download(`reporte-adeudados.pdf`);
|
pdfMake.createPdf(docDefinition as any).download(`reporte-adeudados.pdf`);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
alert.showError((error as { format?: () => string }).format ? (error as { format: () => string }).format() : "Error generando PDF");
|
alert.showError(
|
||||||
|
(error as { format?: () => string }).format
|
||||||
|
? (error as { format: () => string }).format()
|
||||||
|
: "Error generando PDF",
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
eventHandler.setEventType(EVENT_TYPES.CLEAR);
|
eventHandler.setEventType(EVENT_TYPES.CLEAR);
|
||||||
}
|
}
|
||||||
@@ -832,14 +860,24 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
setMethodId={setMethodId}
|
setMethodId={setMethodId}
|
||||||
clientData={clientFilterData}
|
clientData={clientFilterData}
|
||||||
setClientIds={setClientIds}
|
setClientIds={setClientIds}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
filter.setOnFilter(() => { });
|
filter.setOnFilter(() => {});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
bottomToolbar.clear();
|
bottomToolbar.clear();
|
||||||
};
|
};
|
||||||
}, [paymentsTotal, collaboratorFilterData, serviceFilterData, methodFilterData, clientFilterData, clientIds, collaboratorId, serviceId, methodId]);
|
}, [
|
||||||
|
paymentsTotal,
|
||||||
|
collaboratorFilterData,
|
||||||
|
serviceFilterData,
|
||||||
|
methodFilterData,
|
||||||
|
clientFilterData,
|
||||||
|
clientIds,
|
||||||
|
collaboratorId,
|
||||||
|
serviceId,
|
||||||
|
methodId,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -881,45 +919,81 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
loadNotPayedAppointmentsTotal();
|
loadNotPayedAppointmentsTotal();
|
||||||
}, [clientIds, collaboratorId, serviceId, methodId, dateFrom, dateTo, reloadPayments]);
|
}, [clientIds, collaboratorId, serviceId, methodId, dateFrom, dateTo, reloadPayments]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Location />
|
<Location />
|
||||||
|
|
||||||
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
||||||
<div style={{ maxWidth: "800px", margin: "0 auto", paddingBottom: "100px", marginTop: "0px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
maxWidth: "800px",
|
||||||
|
margin: "0 auto",
|
||||||
|
paddingBottom: "100px",
|
||||||
|
marginTop: "0px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{/* Top Status Card */}
|
{/* Top Status Card */}
|
||||||
<div style={{ position: "sticky", top: "70px", zIndex: 100, marginBottom: "50px", display: "flex", flexDirection: "column", background: "white", paddingBottom: "10px", paddingTop: "5px", margin: "0 -10px", paddingLeft: "10px", paddingRight: "10px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
position: "sticky",
|
||||||
{/* Tabs Selector */}
|
top: "70px",
|
||||||
<div style={{ display: "flex", justifyContent: "center", marginBottom: "15px" }}>
|
zIndex: 100,
|
||||||
<ThemeProvider theme={turnosXpressTheme}>
|
marginBottom: "50px",
|
||||||
<div style={{
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
background: "white",
|
||||||
|
paddingBottom: "10px",
|
||||||
|
paddingTop: "5px",
|
||||||
|
margin: "0 -10px",
|
||||||
|
paddingLeft: "10px",
|
||||||
|
paddingRight: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Tabs Selector */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
background: "rgba(255,255,255,0.9)",
|
justifyContent: "center",
|
||||||
backdropFilter: "blur(10px)",
|
marginBottom: "15px",
|
||||||
borderRadius: "30px",
|
}}
|
||||||
padding: "5px",
|
>
|
||||||
boxShadow: "0 4px 15px rgba(0,0,0,0.05)"
|
<ThemeProvider theme={turnosXpressTheme}>
|
||||||
}}>
|
<div
|
||||||
<ButtonMaterial
|
style={{
|
||||||
variant="text"
|
display: "flex",
|
||||||
onClick={() => goTo(`/admin/org/profile/${id}/payments`)}
|
background: "rgba(255,255,255,0.9)",
|
||||||
style={{ borderRadius: "25px", color: "#666", fontWeight: "bold", padding: "8px 25px" }}
|
backdropFilter: "blur(10px)",
|
||||||
|
borderRadius: "30px",
|
||||||
|
padding: "5px",
|
||||||
|
boxShadow: "0 4px 15px rgba(0,0,0,0.05)",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Pagados
|
<ButtonMaterial
|
||||||
</ButtonMaterial>
|
variant="text"
|
||||||
<ButtonMaterial
|
onClick={() => goTo(`/admin/org/profile/${id}/payments`)}
|
||||||
variant="contained"
|
style={{
|
||||||
style={{ borderRadius: "25px", boxShadow: "0 2px 8px rgba(0,0,0,0.1)", fontWeight: "bold", padding: "8px 25px" }}
|
borderRadius: "25px",
|
||||||
>
|
color: "#666",
|
||||||
Adeudados
|
fontWeight: "bold",
|
||||||
</ButtonMaterial>
|
padding: "8px 25px",
|
||||||
</div>
|
}}
|
||||||
</ThemeProvider>
|
>
|
||||||
</div>
|
Pagados
|
||||||
|
</ButtonMaterial>
|
||||||
|
<ButtonMaterial
|
||||||
|
variant="contained"
|
||||||
|
style={{
|
||||||
|
borderRadius: "25px",
|
||||||
|
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
||||||
|
fontWeight: "bold",
|
||||||
|
padding: "8px 25px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Adeudados
|
||||||
|
</ButtonMaterial>
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
layout
|
layout
|
||||||
@@ -928,25 +1002,33 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
padding: isMinimized ? "25px 50px" : "40px 20px",
|
padding: isMinimized ? "25px 50px" : "40px 20px",
|
||||||
borderRadius: isMinimized ? "15px" : "20px"
|
borderRadius: isMinimized ? "15px" : "20px",
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: "linear-gradient(135deg, #FF416C 0%, #FF4B2B 100%)", // Red gradient for debts
|
background: "linear-gradient(135deg, #FF416C 0%, #FF4B2B 100%)", // Red gradient for debts
|
||||||
color: "white",
|
color: "white",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
boxShadow: isMinimized ? "0 4px 15px rgba(0,0,0,0.3)" : "0 10px 30px rgba(0,0,0,0.15)",
|
boxShadow: isMinimized
|
||||||
|
? "0 4px 15px rgba(0,0,0,0.3)"
|
||||||
|
: "0 10px 30px rgba(0,0,0,0.15)",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: isMinimized ? "row" : "column",
|
flexDirection: isMinimized ? "row" : "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: isMinimized ? "space-between" : "center",
|
justifyContent: isMinimized ? "space-between" : "center",
|
||||||
transition: "box-shadow 0.3s ease"
|
transition: "box-shadow 0.3s ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => setForceMinimized(!forceMinimized)}
|
onClick={() => setForceMinimized(!forceMinimized)}
|
||||||
style={{ position: "absolute", top: "10px", left: "10px", color: "rgba(255,255,255,0.7)", zIndex: 10 }}
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "10px",
|
||||||
|
left: "10px",
|
||||||
|
color: "rgba(255,255,255,0.7)",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
||||||
>
|
>
|
||||||
@@ -954,28 +1036,59 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => filter.toggle()}
|
onClick={() => filter.toggle()}
|
||||||
style={{ position: "absolute", top: "10px", right: "10px", color: "rgba(255,255,255,0.7)", zIndex: 10 }}
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "10px",
|
||||||
|
right: "10px",
|
||||||
|
color: "rgba(255,255,255,0.7)",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
title="Filtrar"
|
title="Filtrar"
|
||||||
>
|
>
|
||||||
<FilterAltOutlinedIcon />
|
<FilterAltOutlinedIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<div style={{ position: "absolute", top: "-50px", right: "-50px", width: "150px", height: "150px", borderRadius: "50%", background: "rgba(255,255,255,0.05)" }}></div>
|
<div
|
||||||
<div style={{ position: "absolute", bottom: "-30px", left: "-30px", width: "100px", height: "100px", borderRadius: "50%", background: "rgba(255,255,255,0.05)" }}></div>
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-50px",
|
||||||
|
right: "-50px",
|
||||||
|
width: "150px",
|
||||||
|
height: "150px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "rgba(255,255,255,0.05)",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "-30px",
|
||||||
|
left: "-30px",
|
||||||
|
width: "100px",
|
||||||
|
height: "100px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "rgba(255,255,255,0.05)",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{
|
animate={{
|
||||||
fontSize: isMinimized ? "14px" : "16px",
|
fontSize: isMinimized ? "14px" : "16px",
|
||||||
marginBottom: isMinimized ? "0px" : "10px"
|
marginBottom: isMinimized ? "0px" : "10px",
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "2px",
|
||||||
|
opacity: 0.9,
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "bold", textTransform: "uppercase", letterSpacing: "2px", opacity: 0.9 }}
|
|
||||||
>
|
>
|
||||||
Total Adeudado
|
Total Adeudado
|
||||||
</motion.div>
|
</motion.div>
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{
|
animate={{
|
||||||
fontSize: isMinimized ? "24px" : "56px",
|
fontSize: isMinimized ? "24px" : "56px",
|
||||||
margin: isMinimized ? "0px" : "10px 0"
|
margin: isMinimized ? "0px" : "10px 0",
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "900" }}
|
style={{ fontWeight: "900" }}
|
||||||
>
|
>
|
||||||
@@ -989,16 +1102,29 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
style={{ marginTop: "15px" }}
|
style={{ marginTop: "15px" }}
|
||||||
>
|
>
|
||||||
<div style={{ marginBottom: "15px", width: "250px", maxWidth: "100%" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
marginBottom: "15px",
|
||||||
|
width: "250px",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TextRangeDateModern
|
<TextRangeDateModern
|
||||||
label="Período"
|
label="Período"
|
||||||
dateFrom={dateFrom}
|
dateFrom={dateFrom}
|
||||||
dateTo={dateTo}
|
dateTo={dateTo}
|
||||||
setDateFrom={setDateFrom}
|
setDateFrom={setDateFrom}
|
||||||
setDateTo={setDateTo}
|
setDateTo={setDateTo}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
alignItems: "center",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ButtonMaterial
|
<ButtonMaterial
|
||||||
variant="contained"
|
variant="contained"
|
||||||
startIcon={<PayIcon />}
|
startIcon={<PayIcon />}
|
||||||
@@ -1009,7 +1135,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
borderRadius: "20px",
|
borderRadius: "20px",
|
||||||
padding: "8px 20px",
|
padding: "8px 20px",
|
||||||
textTransform: "none"
|
textTransform: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Pagar Todos
|
Pagar Todos
|
||||||
@@ -1023,10 +1149,13 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
borderRadius: "20px",
|
borderRadius: "20px",
|
||||||
padding: "8px 20px",
|
padding: "8px 20px",
|
||||||
textTransform: "none"
|
textTransform: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PictureAsPdfIcon style={{ fontSize: "18px", marginRight: "5px" }} /> PDF
|
<PictureAsPdfIcon
|
||||||
|
style={{ fontSize: "18px", marginRight: "5px" }}
|
||||||
|
/>{" "}
|
||||||
|
PDF
|
||||||
</ButtonMaterial>
|
</ButtonMaterial>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -1035,10 +1164,22 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dynamic Spacer for layout shift */}
|
{/* Dynamic Spacer for layout shift */}
|
||||||
<div style={{ height: isMinimized ? "150px" : "0px", transition: "height 0.3s ease" }}></div>
|
<div
|
||||||
|
style={{
|
||||||
|
height: isMinimized ? "150px" : "0px",
|
||||||
|
transition: "height 0.3s ease",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
{/* Payments List */}
|
{/* Payments List */}
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "15px", padding: "15px 10px 0 10px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "15px",
|
||||||
|
padding: "15px 10px 0 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{payments?.data.map((payment, index) => (
|
{payments?.data.map((payment, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -1054,31 +1195,72 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
boxShadow: "0 4px 15px rgba(0,0,0,0.05)",
|
boxShadow: "0 4px 15px rgba(0,0,0,0.05)",
|
||||||
borderLeft: `4px solid var(--red)`
|
borderLeft: `4px solid var(--red)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
<div
|
||||||
<div style={{
|
style={{
|
||||||
background: "rgba(255, 75, 43, 0.1)",
|
|
||||||
padding: "10px",
|
|
||||||
borderRadius: "12px",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
gap: "15px",
|
||||||
color: "var(--red)"
|
}}
|
||||||
}}>
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "rgba(255, 75, 43, 0.1)",
|
||||||
|
padding: "10px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
color: "var(--red)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<CreditCardIcon />
|
<CreditCardIcon />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontWeight: "800", fontSize: "15px", color: "#333", marginBottom: "4px" }}>{payment.clientName}</div>
|
<div
|
||||||
<div style={{ fontWeight: "700", fontSize: "13px", color: "var(--purple)", marginBottom: "4px" }}>{payment.serviceName}</div>
|
style={{
|
||||||
|
fontWeight: "800",
|
||||||
|
fontSize: "15px",
|
||||||
|
color: "#333",
|
||||||
|
marginBottom: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{payment.clientName}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontWeight: "700",
|
||||||
|
fontSize: "13px",
|
||||||
|
color: "var(--purple)",
|
||||||
|
marginBottom: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{payment.serviceName}
|
||||||
|
</div>
|
||||||
<div style={{ fontSize: "12px", color: "#888" }}>
|
<div style={{ fontSize: "12px", color: "#888" }}>
|
||||||
{dayjs(payment.createdAt).format("DD MMMM YYYY • HH:mm")} • {payment.employeeName}
|
{dayjs(payment.createdAt).format(
|
||||||
|
"DD MMMM YYYY • HH:mm",
|
||||||
|
)}{" "}
|
||||||
|
• {payment.employeeName}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
<div
|
||||||
<div style={{ fontWeight: "900", fontSize: "16px", color: "var(--red)" }}>
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontWeight: "900",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: "var(--red)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{formatPrice(payment.price)}
|
{formatPrice(payment.price)}
|
||||||
</div>
|
</div>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -1096,10 +1278,22 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{(!payments?.data || payments.data.length === 0) && (
|
{(!payments?.data || payments.data.length === 0) && (
|
||||||
<div style={{ textAlign: "center", padding: "50px", color: "#aaa" }}>
|
<div
|
||||||
<CreditCardIcon sx={{ fontSize: "60px", opacity: 0.2, marginBottom: "15px" }} />
|
style={{ textAlign: "center", padding: "50px", color: "#aaa" }}
|
||||||
<div style={{ fontSize: "18px", fontWeight: "bold" }}>No hay pagos adeudados</div>
|
>
|
||||||
<div style={{ fontSize: "14px", marginTop: "5px" }}>Intenta ajustar los filtros de fecha</div>
|
<CreditCardIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: "60px",
|
||||||
|
opacity: 0.2,
|
||||||
|
marginBottom: "15px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: "18px", fontWeight: "bold" }}>
|
||||||
|
No hay pagos adeudados
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: "14px", marginTop: "5px" }}>
|
||||||
|
Intenta ajustar los filtros de fecha
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
@@ -1107,7 +1301,9 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
|
|
||||||
{/* Pagination */}
|
{/* Pagination */}
|
||||||
{payments && payments.pages > 1 && (
|
{payments && payments.pages > 1 && (
|
||||||
<div style={{ display: "flex", justifyContent: "center", marginTop: "40px" }}>
|
<div
|
||||||
|
style={{ display: "flex", justifyContent: "center", marginTop: "40px" }}
|
||||||
|
>
|
||||||
<Pagination
|
<Pagination
|
||||||
count={payments.pages}
|
count={payments.pages}
|
||||||
page={payments.page}
|
page={payments.page}
|
||||||
@@ -1134,7 +1330,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
data={paymentMethhodFilterData}
|
data={paymentMethhodFilterData}
|
||||||
onChange={(id) => {
|
onChange={(id) => {
|
||||||
setPaymentMethodId(
|
setPaymentMethodId(
|
||||||
id as CLIENT_ACCOUNT_PAYMENT_METHODS
|
id as CLIENT_ACCOUNT_PAYMENT_METHODS,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1185,7 +1381,7 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
data={paymentMethhodFilterData}
|
data={paymentMethhodFilterData}
|
||||||
onChange={(id) => {
|
onChange={(id) => {
|
||||||
setPaymentMethodId(
|
setPaymentMethodId(
|
||||||
id as CLIENT_ACCOUNT_PAYMENT_METHODS
|
id as CLIENT_ACCOUNT_PAYMENT_METHODS,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1219,7 +1415,6 @@ export default function OrganizationNotPayedAppointments() {
|
|||||||
</DialogActions>
|
</DialogActions>
|
||||||
</>
|
</>
|
||||||
</DialogWindow>
|
</DialogWindow>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</SecureByPlan>
|
</SecureByPlan>
|
||||||
</>
|
</>
|
||||||
|
|||||||
+345
-116
@@ -47,6 +47,7 @@ import SearchOffIcon from "@mui/icons-material/SearchOff";
|
|||||||
import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
|
import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
|
||||||
import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
|
import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
|
||||||
import FilterAltOutlinedIcon from "@mui/icons-material/FilterAltOutlined";
|
import FilterAltOutlinedIcon from "@mui/icons-material/FilterAltOutlined";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -68,8 +69,12 @@ const FilterContent = (props: FilterContentProps) => {
|
|||||||
const [clientFilterContent] = useState<TextObjectModalContent>({
|
const [clientFilterContent] = useState<TextObjectModalContent>({
|
||||||
header: (
|
header: (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>Seleccionar Cliente:</div>
|
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>
|
||||||
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>Ingrese el nombre del cliente para buscarlo.</p>
|
Seleccionar Cliente:
|
||||||
|
</div>
|
||||||
|
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>
|
||||||
|
Ingrese el nombre del cliente para buscarlo.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
bottom: <div> </div>,
|
bottom: <div> </div>,
|
||||||
@@ -81,8 +86,12 @@ const FilterContent = (props: FilterContentProps) => {
|
|||||||
const [collaboratorFilterContent] = useState<TextObjectModalContent>({
|
const [collaboratorFilterContent] = useState<TextObjectModalContent>({
|
||||||
header: (
|
header: (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>Seleccionar Colaborador:</div>
|
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>
|
||||||
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>Ingrese el nombre del colaborador para buscarlo.</p>
|
Seleccionar Colaborador:
|
||||||
|
</div>
|
||||||
|
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>
|
||||||
|
Ingrese el nombre del colaborador para buscarlo.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
bottom: <div> </div>,
|
bottom: <div> </div>,
|
||||||
@@ -94,8 +103,12 @@ const FilterContent = (props: FilterContentProps) => {
|
|||||||
const [serviceFilterContent] = useState<TextObjectModalContent>({
|
const [serviceFilterContent] = useState<TextObjectModalContent>({
|
||||||
header: (
|
header: (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>Seleccionar Servicio:</div>
|
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>
|
||||||
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>Ingrese el nombre del servicio para buscarlo.</p>
|
Seleccionar Servicio:
|
||||||
|
</div>
|
||||||
|
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>
|
||||||
|
Ingrese el nombre del servicio para buscarlo.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
bottom: <div> </div>,
|
bottom: <div> </div>,
|
||||||
@@ -107,8 +120,12 @@ const FilterContent = (props: FilterContentProps) => {
|
|||||||
const [methodFilterContent] = useState<TextObjectModalContent>({
|
const [methodFilterContent] = useState<TextObjectModalContent>({
|
||||||
header: (
|
header: (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>Seleccionar Método de Pago:</div>
|
<div style={{ fontWeight: "700", fontSize: "14px", paddingTop: "7px" }}>
|
||||||
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>Ingrese el nombre del método de pago para buscarlo.</p>
|
Seleccionar Método de Pago:
|
||||||
|
</div>
|
||||||
|
<p style={{ fontWeight: "500", fontSize: "13px", paddingTop: "2px" }}>
|
||||||
|
Ingrese el nombre del método de pago para buscarlo.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
bottom: <div> </div>,
|
bottom: <div> </div>,
|
||||||
@@ -152,6 +169,7 @@ export default function OrganizationEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const filter = useFilterStore();
|
const filter = useFilterStore();
|
||||||
@@ -168,7 +186,9 @@ export default function OrganizationEdit() {
|
|||||||
const [clientFilterData, setClientFilterData] = useState<TextObjectFilterResult[]>([]);
|
const [clientFilterData, setClientFilterData] = useState<TextObjectFilterResult[]>([]);
|
||||||
const [clientIds, setClientIds] = useState<string[]>([]);
|
const [clientIds, setClientIds] = useState<string[]>([]);
|
||||||
|
|
||||||
const [collaboratorFilterData, setCollaboratorFilterData] = useState<TextObjectFilterResult[]>([]);
|
const [collaboratorFilterData, setCollaboratorFilterData] = useState<TextObjectFilterResult[]>(
|
||||||
|
[],
|
||||||
|
);
|
||||||
const [collaboratorId, setCollaboratorId] = useState<string>("");
|
const [collaboratorId, setCollaboratorId] = useState<string>("");
|
||||||
|
|
||||||
const [serviceFilterData, setServiceFilterData] = useState<TextObjectFilterResult[]>([]);
|
const [serviceFilterData, setServiceFilterData] = useState<TextObjectFilterResult[]>([]);
|
||||||
@@ -188,7 +208,6 @@ export default function OrganizationEdit() {
|
|||||||
|
|
||||||
const generarReporte = async () => {
|
const generarReporte = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const pdfMake = await import("pdfmake/build/pdfmake");
|
const pdfMake = await import("pdfmake/build/pdfmake");
|
||||||
const pdfFonts = (await import("pdfmake/build/vfs_fonts")) as any;
|
const pdfFonts = (await import("pdfmake/build/vfs_fonts")) as any;
|
||||||
pdfMake.vfs = pdfFonts.pdfMake ? pdfFonts.pdfMake.vfs : pdfFonts.vfs;
|
pdfMake.vfs = pdfFonts.pdfMake ? pdfFonts.pdfMake.vfs : pdfFonts.vfs;
|
||||||
@@ -201,7 +220,7 @@ export default function OrganizationEdit() {
|
|||||||
serviceId: serviceId ? serviceId : undefined,
|
serviceId: serviceId ? serviceId : undefined,
|
||||||
employeeId: collaboratorId ? collaboratorId : undefined,
|
employeeId: collaboratorId ? collaboratorId : undefined,
|
||||||
method: methodId ? (methodId as any) : undefined,
|
method: methodId ? (methodId as any) : undefined,
|
||||||
sessionUser: SessionInfo.userId
|
sessionUser: SessionInfo.userId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!report.items || report.items.length === 0) {
|
if (!report.items || report.items.length === 0) {
|
||||||
@@ -218,86 +237,114 @@ export default function OrganizationEdit() {
|
|||||||
reader.onloadend = () => resolve(reader.result as string);
|
reader.onloadend = () => resolve(reader.result as string);
|
||||||
reader.readAsDataURL(blob);
|
reader.readAsDataURL(blob);
|
||||||
});
|
});
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
const tableBody: any[] = [
|
const tableBody: any[] = [
|
||||||
[
|
[
|
||||||
{ text: "Cliente", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
{ text: "Cliente", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
{ text: "Datos del Turno", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
{ text: "Datos del Turno", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
{ text: "Monto", bold: true, color: "#333333", fillColor: "#f5f5f5" }
|
{ text: "Monto", bold: true, color: "#333333", fillColor: "#f5f5f5" },
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
report.items.forEach(item => {
|
report.items.forEach((item) => {
|
||||||
tableBody.push([
|
tableBody.push([
|
||||||
item.clientName || "-",
|
item.clientName || "-",
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: `${item.serviceName || "-"}\n`, bold: true, fontSize: 11 },
|
{ text: `${item.serviceName || "-"}\n`, bold: true, fontSize: 11 },
|
||||||
`Prof: ${item.employeeName || "-"}\nFecha: ${dayjs(item.appointmentDate).format("DD/MM/YYYY HH:mm")} hs\nMétodo: ${item.method || "-"}`
|
`Prof: ${item.employeeName || "-"}\nFecha: ${dayjs(item.appointmentDate).format("DD/MM/YYYY HH:mm")} hs\nMétodo: ${item.method || "-"}`,
|
||||||
],
|
],
|
||||||
fontSize: 10
|
fontSize: 10,
|
||||||
},
|
},
|
||||||
{ text: "$" + item.price.toLocaleString("es-AR"), alignment: "right" }
|
{ text: "$" + item.price.toLocaleString("es-AR"), alignment: "right" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
tableBody.push([
|
tableBody.push([
|
||||||
{ text: "TOTAL PROCESADO", bold: true, colSpan: 2, alignment: "right" },
|
{ text: "TOTAL PROCESADO", bold: true, colSpan: 2, alignment: "right" },
|
||||||
{},
|
{},
|
||||||
{ text: "$" + report.totalAmount.toLocaleString("es-AR"), bold: true, alignment: "right" }
|
{
|
||||||
|
text: "$" + report.totalAmount.toLocaleString("es-AR"),
|
||||||
|
bold: true,
|
||||||
|
alignment: "right",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const docDefinition: unknown = {
|
const docDefinition: unknown = {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
columns: [
|
columns: [
|
||||||
{ text: "Reporte de Cobros Procesados", fontSize: 18, bold: true, margin: [0, 0, 0, 10], width: '*' },
|
{
|
||||||
...(logoDataUrl ? [{ image: logoDataUrl, width: 45, margin: [0, 0, 0, 10], alignment: 'right' }] : [])
|
text: "Reporte de Cobros Procesados",
|
||||||
]
|
fontSize: 18,
|
||||||
|
bold: true,
|
||||||
|
margin: [0, 0, 0, 10],
|
||||||
|
width: "*",
|
||||||
|
},
|
||||||
|
...(logoDataUrl
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
image: logoDataUrl,
|
||||||
|
width: 45,
|
||||||
|
margin: [0, 0, 0, 10],
|
||||||
|
alignment: "right",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{ text: `Filtros aplicados:`, bold: true, margin: [0, 0, 0, 5] },
|
{ text: `Filtros aplicados:`, bold: true, margin: [0, 0, 0, 5] },
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: "Clientes Seleccionados: ", bold: true },
|
{ text: "Clientes Seleccionados: ", bold: true },
|
||||||
`${clientIds.length > 0 ? clientIds.length : "Todos"}`
|
`${clientIds.length > 0 ? clientIds.length : "Todos"}`,
|
||||||
],
|
],
|
||||||
margin: [0, 0, 0, 2]
|
margin: [0, 0, 0, 2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: [
|
text: [
|
||||||
{ text: "Período: ", bold: true },
|
{ text: "Período: ", bold: true },
|
||||||
`${dateFrom ? dateFrom.format("DD/MM/YYYY") : "Inicio"} al ${dateTo ? dateTo.format("DD/MM/YYYY") : "Fin"}`
|
`${dateFrom ? dateFrom.format("DD/MM/YYYY") : "Inicio"} al ${dateTo ? dateTo.format("DD/MM/YYYY") : "Fin"}`,
|
||||||
],
|
],
|
||||||
margin: [0, 0, 0, 20]
|
margin: [0, 0, 0, 20],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
table: {
|
table: {
|
||||||
headerRows: 1,
|
headerRows: 1,
|
||||||
widths: [120, "*", "auto"],
|
widths: [120, "*", "auto"],
|
||||||
body: tableBody
|
body: tableBody,
|
||||||
},
|
},
|
||||||
layout: "lightHorizontalLines"
|
layout: "lightHorizontalLines",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((window as unknown as { Android: any }).Android && (window as unknown as { Android: any }).Android.savePdf) {
|
if (
|
||||||
|
(window as unknown as { Android: any }).Android &&
|
||||||
|
(window as unknown as { Android: any }).Android.savePdf
|
||||||
|
) {
|
||||||
pdfMake.createPdf(docDefinition as any).getBase64((data: any) => {
|
pdfMake.createPdf(docDefinition as any).getBase64((data: any) => {
|
||||||
(window as unknown as { Android: any }).Android?.savePdf(data, `reporte-procesados.pdf`);
|
(window as unknown as { Android: any }).Android?.savePdf(
|
||||||
|
data,
|
||||||
|
`reporte-procesados.pdf`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pdfMake.createPdf(docDefinition as any).download(`reporte-procesados.pdf`);
|
pdfMake.createPdf(docDefinition as any).download(`reporte-procesados.pdf`);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
alert.showError((error as { format?: () => string }).format ? (error as { format: () => string }).format() : "Error generando PDF");
|
alert.showError(
|
||||||
|
(error as { format?: () => string }).format
|
||||||
|
? (error as { format: () => string }).format()
|
||||||
|
: "Error generando PDF",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const handleScroll = (e: Event) => {
|
||||||
const handleScroll = (e: Event) => {
|
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
// Check if it's a DOM element scrolling
|
// Check if it's a DOM element scrolling
|
||||||
if (target && target.scrollTop !== undefined) {
|
if (target && target.scrollTop !== undefined) {
|
||||||
@@ -389,15 +436,23 @@ export default function OrganizationEdit() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const cFilter: FindClientsParams = { companyId: id };
|
const cFilter: FindClientsParams = { companyId: id };
|
||||||
filterObjects<FindClientsParams>("clients/filter-all", cFilter).then((res) => setClientFilterData(res));
|
filterObjects<FindClientsParams>("clients/filter-all", cFilter).then((res) =>
|
||||||
|
setClientFilterData(res),
|
||||||
|
);
|
||||||
|
|
||||||
const eFilter: FindEmployeesParams = { companyId: id };
|
const eFilter: FindEmployeesParams = { companyId: id };
|
||||||
filterObjects<FindEmployeesParams>("employees/filter-all", eFilter).then((res) => setCollaboratorFilterData(res));
|
filterObjects<FindEmployeesParams>("employees/filter-all", eFilter).then((res) =>
|
||||||
|
setCollaboratorFilterData(res),
|
||||||
|
);
|
||||||
|
|
||||||
const sFilter: FindServicesParams = { companyId: id };
|
const sFilter: FindServicesParams = { companyId: id };
|
||||||
filterObjects<FindServicesParams>("services/filter-all", sFilter).then((res) => setServiceFilterData(res));
|
filterObjects<FindServicesParams>("services/filter-all", sFilter).then((res) =>
|
||||||
|
setServiceFilterData(res),
|
||||||
|
);
|
||||||
|
|
||||||
setMethodFilterData(paymentMethods.map((m) => ({ id: m.id, text: m.name, name: m.name, image: "" })));
|
setMethodFilterData(
|
||||||
|
paymentMethods.map((m) => ({ id: m.id, text: m.name, name: m.name, image: "" })),
|
||||||
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -413,18 +468,31 @@ export default function OrganizationEdit() {
|
|||||||
setMethodId={setMethodId}
|
setMethodId={setMethodId}
|
||||||
clientData={clientFilterData}
|
clientData={clientFilterData}
|
||||||
setClientIds={setClientIds}
|
setClientIds={setClientIds}
|
||||||
clientIds={clientIds}
|
clientIds={clientIds}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
filter.setOnFilter(() => { });
|
filter.setOnFilter(() => {});
|
||||||
}, [collaboratorFilterData, serviceFilterData, methodFilterData, clientFilterData]);
|
}, [collaboratorFilterData, serviceFilterData, methodFilterData, clientFilterData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
location.clear();
|
location.clear();
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
location.add({ url: "/admin/org", title: "Organizaciones", icon: null });
|
location.add({ url: "/admin/org", title: "Organizaciones", icon: null });
|
||||||
location.add({ url: "/admin/org/profile/" + id, title: "Perfil", icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" /> });
|
location.add({
|
||||||
location.add({ url: "/admin/org/profile/" + id, title: "Pagos", icon: <PaymentsIcon sx={{ fontSize: "32px", mr: "10px" }} /> });
|
url: "/admin/org/profile/" + id,
|
||||||
|
title: "Perfil",
|
||||||
|
icon: <StorefrontOutlinedIcon sx={{ mr: 0.5 }} fontSize="inherit" />,
|
||||||
|
});
|
||||||
|
location.add({
|
||||||
|
url: "/admin/org/profile/" + id,
|
||||||
|
title: "Pagos",
|
||||||
|
icon: <PaymentsIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -444,41 +512,81 @@ export default function OrganizationEdit() {
|
|||||||
<Location />
|
<Location />
|
||||||
|
|
||||||
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
<SecureByPlan content={SECURE_CONTENTS.PAYMENTS} companyId={id}>
|
||||||
<div style={{ maxWidth: "800px", margin: "0 auto", paddingBottom: "100px", marginTop: "0px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
maxWidth: "800px",
|
||||||
|
margin: "0 auto",
|
||||||
|
paddingBottom: "100px",
|
||||||
|
marginTop: "0px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{/* Sentinel element to detect scroll */}
|
{/* Sentinel element to detect scroll */}
|
||||||
<div ref={sentinelRef} style={{ height: "1px", width: "100%" }}></div>
|
<div ref={sentinelRef} style={{ height: "1px", width: "100%" }}></div>
|
||||||
|
|
||||||
{/* Top Status Card */}
|
{/* Top Status Card */}
|
||||||
<div style={{ position: "sticky", top: "70px", zIndex: 100, marginBottom: "50px", display: "flex", flexDirection: "column", background: "white", paddingBottom: "10px", paddingTop: "5px", margin: "0 -10px", paddingLeft: "10px", paddingRight: "10px" }}>
|
<div
|
||||||
|
style={{
|
||||||
{/* Tabs Selector */}
|
position: "sticky",
|
||||||
<div style={{ display: "flex", justifyContent: "center", marginBottom: "15px" }}>
|
top: "70px",
|
||||||
<ThemeProvider theme={turnosXpressTheme}>
|
zIndex: 100,
|
||||||
<div style={{
|
marginBottom: "50px",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
background: "white",
|
||||||
|
paddingBottom: "10px",
|
||||||
|
paddingTop: "5px",
|
||||||
|
margin: "0 -10px",
|
||||||
|
paddingLeft: "10px",
|
||||||
|
paddingRight: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Tabs Selector */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
background: "rgba(255,255,255,0.9)",
|
justifyContent: "center",
|
||||||
backdropFilter: "blur(10px)",
|
marginBottom: "15px",
|
||||||
borderRadius: "30px",
|
}}
|
||||||
padding: "5px",
|
>
|
||||||
boxShadow: "0 4px 15px rgba(0,0,0,0.05)"
|
<ThemeProvider theme={turnosXpressTheme}>
|
||||||
}}>
|
<div
|
||||||
<ButtonMaterial
|
style={{
|
||||||
variant="contained"
|
display: "flex",
|
||||||
style={{ borderRadius: "25px", boxShadow: "0 2px 8px rgba(0,0,0,0.1)", fontWeight: "bold", padding: "8px 25px" }}
|
background: "rgba(255,255,255,0.9)",
|
||||||
|
backdropFilter: "blur(10px)",
|
||||||
|
borderRadius: "30px",
|
||||||
|
padding: "5px",
|
||||||
|
boxShadow: "0 4px 15px rgba(0,0,0,0.05)",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Pagados
|
<ButtonMaterial
|
||||||
</ButtonMaterial>
|
variant="contained"
|
||||||
<ButtonMaterial
|
style={{
|
||||||
variant="text"
|
borderRadius: "25px",
|
||||||
onClick={() => goTo(`/admin/org/profile/${id}/payments/not-payed`)}
|
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
||||||
style={{ borderRadius: "25px", color: "#666", fontWeight: "bold", padding: "8px 25px" }}
|
fontWeight: "bold",
|
||||||
>
|
padding: "8px 25px",
|
||||||
Adeudados
|
}}
|
||||||
</ButtonMaterial>
|
>
|
||||||
</div>
|
Pagados
|
||||||
</ThemeProvider>
|
</ButtonMaterial>
|
||||||
</div>
|
<ButtonMaterial
|
||||||
|
variant="text"
|
||||||
|
onClick={() =>
|
||||||
|
goTo(`/admin/org/profile/${id}/payments/not-payed`)
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
borderRadius: "25px",
|
||||||
|
color: "#666",
|
||||||
|
fontWeight: "bold",
|
||||||
|
padding: "8px 25px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Adeudados
|
||||||
|
</ButtonMaterial>
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
layout
|
layout
|
||||||
@@ -487,25 +595,33 @@ export default function OrganizationEdit() {
|
|||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
padding: isMinimized ? "25px 50px" : "40px 20px",
|
padding: isMinimized ? "25px 50px" : "40px 20px",
|
||||||
borderRadius: isMinimized ? "15px" : "20px"
|
borderRadius: isMinimized ? "15px" : "20px",
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
background: "linear-gradient(135deg, #4b6cb7 0%, #182848 100%)",
|
background: "linear-gradient(135deg, #4b6cb7 0%, #182848 100%)",
|
||||||
color: "white",
|
color: "white",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
boxShadow: isMinimized ? "0 4px 15px rgba(0,0,0,0.3)" : "0 10px 30px rgba(0,0,0,0.15)",
|
boxShadow: isMinimized
|
||||||
|
? "0 4px 15px rgba(0,0,0,0.3)"
|
||||||
|
: "0 10px 30px rgba(0,0,0,0.15)",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: isMinimized ? "row" : "column",
|
flexDirection: isMinimized ? "row" : "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: isMinimized ? "space-between" : "center",
|
justifyContent: isMinimized ? "space-between" : "center",
|
||||||
transition: "box-shadow 0.3s ease"
|
transition: "box-shadow 0.3s ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => setForceMinimized(!forceMinimized)}
|
onClick={() => setForceMinimized(!forceMinimized)}
|
||||||
style={{ position: "absolute", top: "10px", left: "10px", color: "rgba(255,255,255,0.7)", zIndex: 10 }}
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "10px",
|
||||||
|
left: "10px",
|
||||||
|
color: "rgba(255,255,255,0.7)",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
title={forceMinimized ? "Maximizar" : "Minimizar"}
|
||||||
>
|
>
|
||||||
@@ -513,28 +629,59 @@ export default function OrganizationEdit() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => filter.toggle()}
|
onClick={() => filter.toggle()}
|
||||||
style={{ position: "absolute", top: "10px", right: "10px", color: "rgba(255,255,255,0.7)", zIndex: 10 }}
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "10px",
|
||||||
|
right: "10px",
|
||||||
|
color: "rgba(255,255,255,0.7)",
|
||||||
|
zIndex: 10,
|
||||||
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
title="Filtrar"
|
title="Filtrar"
|
||||||
>
|
>
|
||||||
<FilterAltOutlinedIcon />
|
<FilterAltOutlinedIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<div style={{ position: "absolute", top: "-50px", right: "-50px", width: "150px", height: "150px", borderRadius: "50%", background: "rgba(255,255,255,0.05)" }}></div>
|
<div
|
||||||
<div style={{ position: "absolute", bottom: "-30px", left: "-30px", width: "100px", height: "100px", borderRadius: "50%", background: "rgba(255,255,255,0.05)" }}></div>
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "-50px",
|
||||||
|
right: "-50px",
|
||||||
|
width: "150px",
|
||||||
|
height: "150px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "rgba(255,255,255,0.05)",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "-30px",
|
||||||
|
left: "-30px",
|
||||||
|
width: "100px",
|
||||||
|
height: "100px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "rgba(255,255,255,0.05)",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{
|
animate={{
|
||||||
fontSize: isMinimized ? "14px" : "16px",
|
fontSize: isMinimized ? "14px" : "16px",
|
||||||
marginBottom: isMinimized ? "0px" : "10px"
|
marginBottom: isMinimized ? "0px" : "10px",
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "2px",
|
||||||
|
opacity: 0.9,
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "bold", textTransform: "uppercase", letterSpacing: "2px", opacity: 0.9 }}
|
|
||||||
>
|
>
|
||||||
Total Recaudado
|
Total Recaudado
|
||||||
</motion.div>
|
</motion.div>
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{
|
animate={{
|
||||||
fontSize: isMinimized ? "24px" : "56px",
|
fontSize: isMinimized ? "24px" : "56px",
|
||||||
margin: isMinimized ? "0px" : "10px 0"
|
margin: isMinimized ? "0px" : "10px 0",
|
||||||
}}
|
}}
|
||||||
style={{ fontWeight: "900" }}
|
style={{ fontWeight: "900" }}
|
||||||
>
|
>
|
||||||
@@ -547,7 +694,16 @@ export default function OrganizationEdit() {
|
|||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
style={{ fontSize: "14px", opacity: 0.8 }}
|
style={{ fontSize: "14px", opacity: 0.8 }}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap", justifyContent: "center", marginTop: "10px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
alignItems: "center",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div style={{ width: "250px", maxWidth: "100%" }}>
|
<div style={{ width: "250px", maxWidth: "100%" }}>
|
||||||
<TextRangeDateModern
|
<TextRangeDateModern
|
||||||
label="Período"
|
label="Período"
|
||||||
@@ -567,10 +723,13 @@ export default function OrganizationEdit() {
|
|||||||
borderRadius: "20px",
|
borderRadius: "20px",
|
||||||
padding: "8px 20px",
|
padding: "8px 20px",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
height: "56px"
|
height: "56px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PictureAsPdfIcon style={{ fontSize: "18px", marginRight: "5px" }} /> PDF
|
<PictureAsPdfIcon
|
||||||
|
style={{ fontSize: "18px", marginRight: "5px" }}
|
||||||
|
/>{" "}
|
||||||
|
PDF
|
||||||
</ButtonMaterial>
|
</ButtonMaterial>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -579,10 +738,22 @@ export default function OrganizationEdit() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dynamic Spacer for layout shift */}
|
{/* Dynamic Spacer for layout shift */}
|
||||||
<div style={{ height: isMinimized ? "100px" : "0px", transition: "height 0.3s ease" }}></div>
|
<div
|
||||||
|
style={{
|
||||||
|
height: isMinimized ? "100px" : "0px",
|
||||||
|
transition: "height 0.3s ease",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
|
||||||
{/* Payments List */}
|
{/* Payments List */}
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "12px", paddingTop: "15px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "12px",
|
||||||
|
paddingTop: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{dataList.length > 0 ? (
|
{dataList.length > 0 ? (
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{dataList.map((payment, index) => (
|
{dataList.map((payment, index) => (
|
||||||
@@ -602,43 +773,85 @@ export default function OrganizationEdit() {
|
|||||||
padding: "16px 20px",
|
padding: "16px 20px",
|
||||||
boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
|
boxShadow: "0 4px 12px rgba(0,0,0,0.05)",
|
||||||
borderLeft: "5px solid #28a745",
|
borderLeft: "5px solid #28a745",
|
||||||
position: "relative"
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "15px", flex: 1 }}>
|
<div
|
||||||
<div style={{
|
style={{
|
||||||
width: "50px",
|
|
||||||
height: "50px",
|
|
||||||
borderRadius: "12px",
|
|
||||||
backgroundColor: "rgba(40, 167, 69, 0.1)",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
gap: "15px",
|
||||||
color: "#28a745"
|
flex: 1,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "50px",
|
||||||
|
height: "50px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
backgroundColor: "rgba(40, 167, 69, 0.1)",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
color: "#28a745",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{getPaymentIcon(payment.method)}
|
{getPaymentIcon(payment.method)}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<div style={{ fontSize: "16px", fontWeight: "bold", color: "#333", marginBottom: "2px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "16px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#333",
|
||||||
|
marginBottom: "2px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{payment.clientName}
|
{payment.clientName}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: "14px", color: "var(--wine-dark)", fontWeight: "bold", marginBottom: "4px" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "14px",
|
||||||
|
color: "var(--wine-dark)",
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{payment.serviceName}
|
{payment.serviceName}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", gap: "10px", fontSize: "12px", color: "#888" }}>
|
<div
|
||||||
<span>{dayjs(payment.createdAt).format("DD MMMM YYYY • HH:mm")}</span>
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
fontSize: "12px",
|
||||||
|
color: "#888",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{dayjs(payment.createdAt).format(
|
||||||
|
"DD MMMM YYYY • HH:mm",
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>{payment.employeeName}</span>
|
<span>{payment.employeeName}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
<div
|
||||||
<div style={{
|
style={{
|
||||||
fontSize: "20px",
|
display: "flex",
|
||||||
fontWeight: "900",
|
alignItems: "center",
|
||||||
color: "#28a745",
|
gap: "15px",
|
||||||
textAlign: "right"
|
}}
|
||||||
}}>
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "20px",
|
||||||
|
fontWeight: "900",
|
||||||
|
color: "#28a745",
|
||||||
|
textAlign: "right",
|
||||||
|
}}
|
||||||
|
>
|
||||||
+{formatPrice(payment.price)}
|
+{formatPrice(payment.price)}
|
||||||
</div>
|
</div>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -646,14 +859,18 @@ export default function OrganizationEdit() {
|
|||||||
size="small"
|
size="small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
confirm.show(
|
confirm.show(
|
||||||
"¿Estás seguro que quieres eliminar el pago de " + payment.clientName + "?",
|
"¿Estás seguro que quieres eliminar el pago de " +
|
||||||
|
payment.clientName +
|
||||||
|
"?",
|
||||||
() => deletePaymentHandler(payment.id),
|
() => deletePaymentHandler(payment.id),
|
||||||
() => { }
|
() => {},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "rgba(220, 53, 69, 0.05)",
|
backgroundColor: "rgba(220, 53, 69, 0.05)",
|
||||||
"&:hover": { backgroundColor: "rgba(220, 53, 69, 0.15)" }
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(220, 53, 69, 0.15)",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DeleteIcon fontSize="small" />
|
<DeleteIcon fontSize="small" />
|
||||||
@@ -666,17 +883,29 @@ export default function OrganizationEdit() {
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
style={{ textAlign: "center", padding: "60px 20px", backgroundColor: "#fff", borderRadius: "15px", border: "1px dashed #ccc" }}
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
|
padding: "60px 20px",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderRadius: "15px",
|
||||||
|
border: "1px dashed #ccc",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SearchOffIcon sx={{ fontSize: "64px", color: "#ccc", marginBottom: "15px" }} />
|
<SearchOffIcon
|
||||||
|
sx={{ fontSize: "64px", color: "#ccc", marginBottom: "15px" }}
|
||||||
|
/>
|
||||||
<h2 style={{ margin: 0, color: "#999" }}>Sin Pagos</h2>
|
<h2 style={{ margin: 0, color: "#999" }}>Sin Pagos</h2>
|
||||||
<p style={{ color: "#aaa" }}>No se encontraron pagos registrados para este período.</p>
|
<p style={{ color: "#aaa" }}>
|
||||||
|
No se encontraron pagos registrados para este período.
|
||||||
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{payments && payments.pages > 1 && (
|
{payments && payments.pages > 1 && (
|
||||||
<div style={{ display: "flex", justifyContent: "center", marginTop: "40px" }}>
|
<div
|
||||||
|
style={{ display: "flex", justifyContent: "center", marginTop: "40px" }}
|
||||||
|
>
|
||||||
<Pagination
|
<Pagination
|
||||||
count={payments.pages}
|
count={payments.pages}
|
||||||
page={payments.page}
|
page={payments.page}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import Avatar from "@components/Avatar/Avatar";
|
|||||||
import Button from "@core/app/components/Button/Button";
|
import Button from "@core/app/components/Button/Button";
|
||||||
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
||||||
import { getMondayWeekStart } from "@core/helpers/week";
|
import { getMondayWeekStart } from "@core/helpers/week";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
dayjs.locale("es");
|
dayjs.locale("es");
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ export default function Schedules() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -38,6 +40,8 @@ export default function Schedules() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -55,6 +59,10 @@ export default function Schedules() {
|
|||||||
title: "Horarios Habilitados",
|
title: "Horarios Habilitados",
|
||||||
icon: null,
|
icon: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -118,7 +126,7 @@ export default function Schedules() {
|
|||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+22
-11
@@ -80,7 +80,7 @@ export default function OrganizationService() {
|
|||||||
const [serviceDiscountName, setServiceDiscountName] = useState<string | undefined>(undefined);
|
const [serviceDiscountName, setServiceDiscountName] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
const [servicePublished, setServicePublished] = useState<SERVICE_PUBLISHED_STATUS | undefined>(
|
const [servicePublished, setServicePublished] = useState<SERVICE_PUBLISHED_STATUS | undefined>(
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
||||||
@@ -149,7 +149,7 @@ export default function OrganizationService() {
|
|||||||
>
|
>
|
||||||
Aplicar Descuento
|
Aplicar Descuento
|
||||||
</ButtonMaterial>
|
</ButtonMaterial>
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -271,8 +271,12 @@ export default function OrganizationService() {
|
|||||||
setServiceDiscountType(response.discountType);
|
setServiceDiscountType(response.discountType);
|
||||||
setServiceDiscountValue(response.discountValue);
|
setServiceDiscountValue(response.discountValue);
|
||||||
setServiceDiscountName(response.discountName);
|
setServiceDiscountName(response.discountName);
|
||||||
setShowPublicScores(response.showPublicScores !== undefined ? response.showPublicScores : true);
|
setShowPublicScores(
|
||||||
setShowPublicOpinions(response.showPublicOpinions !== undefined ? response.showPublicOpinions : true);
|
response.showPublicScores !== undefined ? response.showPublicScores : true,
|
||||||
|
);
|
||||||
|
setShowPublicOpinions(
|
||||||
|
response.showPublicOpinions !== undefined ? response.showPublicOpinions : true,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -283,7 +287,7 @@ export default function OrganizationService() {
|
|||||||
const formatDiscount = (
|
const formatDiscount = (
|
||||||
value: number | undefined,
|
value: number | undefined,
|
||||||
type: string | undefined,
|
type: string | undefined,
|
||||||
name: string | undefined
|
name: string | undefined,
|
||||||
): string => {
|
): string => {
|
||||||
if (value === undefined || value === null || type === undefined || type === null) {
|
if (value === undefined || value === null || type === undefined || type === null) {
|
||||||
return "";
|
return "";
|
||||||
@@ -464,7 +468,7 @@ export default function OrganizationService() {
|
|||||||
setServicePublished(
|
setServicePublished(
|
||||||
checked
|
checked
|
||||||
? SERVICE_PUBLISHED_STATUS.PUBLISHED
|
? SERVICE_PUBLISHED_STATUS.PUBLISHED
|
||||||
: SERVICE_PUBLISHED_STATUS.PRIVATE
|
: SERVICE_PUBLISHED_STATUS.PRIVATE,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -506,10 +510,15 @@ export default function OrganizationService() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones y opiniones de este servicio en páginas públicas. Disponible para planes pagos.
|
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones y opiniones de este
|
||||||
|
servicio en páginas públicas. Disponible para planes pagos.
|
||||||
</MaterialAlert>
|
</MaterialAlert>
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}>
|
<div
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}
|
||||||
|
>
|
||||||
<Switch
|
<Switch
|
||||||
checked={showPublicScores}
|
checked={showPublicScores}
|
||||||
disabled={!canEditPublicRatingFlags}
|
disabled={!canEditPublicRatingFlags}
|
||||||
@@ -520,7 +529,9 @@ export default function OrganizationService() {
|
|||||||
/>
|
/>
|
||||||
Mostrar puntuaciones públicas
|
Mostrar puntuaciones públicas
|
||||||
</label>
|
</label>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
<label
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}
|
||||||
|
>
|
||||||
<Switch
|
<Switch
|
||||||
checked={showPublicOpinions}
|
checked={showPublicOpinions}
|
||||||
disabled={!canEditPublicRatingFlags}
|
disabled={!canEditPublicRatingFlags}
|
||||||
@@ -567,7 +578,7 @@ export default function OrganizationService() {
|
|||||||
() => {
|
() => {
|
||||||
deleteDiscountHandler();
|
deleteDiscountHandler();
|
||||||
},
|
},
|
||||||
() => {}
|
() => {},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ import {
|
|||||||
WhatsappIcon as WhatsAppShareIcon,
|
WhatsappIcon as WhatsAppShareIcon,
|
||||||
TwitterIcon,
|
TwitterIcon,
|
||||||
EmailIcon,
|
EmailIcon,
|
||||||
TelegramIcon
|
TelegramIcon,
|
||||||
} from "react-share";
|
} from "react-share";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -43,6 +44,7 @@ export default function Org() {
|
|||||||
const urlData = useParams<UrlData>();
|
const urlData = useParams<UrlData>();
|
||||||
const id = urlData.id;
|
const id = urlData.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
|
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -58,6 +60,8 @@ export default function Org() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -75,6 +79,10 @@ export default function Org() {
|
|||||||
title: "Mis servicios",
|
title: "Mis servicios",
|
||||||
icon: <StorefrontOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <StorefrontOutlinedIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -105,7 +113,7 @@ export default function Org() {
|
|||||||
<div
|
<div
|
||||||
className={style.serviceCard}
|
className={style.serviceCard}
|
||||||
style={{
|
style={{
|
||||||
borderLeft: `6px solid ${data.color}`
|
borderLeft: `6px solid ${data.color}`,
|
||||||
}}
|
}}
|
||||||
onClick={() => handleServiceClick(data.id)}
|
onClick={() => handleServiceClick(data.id)}
|
||||||
>
|
>
|
||||||
@@ -115,7 +123,11 @@ export default function Org() {
|
|||||||
<div className={style.serviceInfo}>
|
<div className={style.serviceInfo}>
|
||||||
<h1>{data.name}</h1>
|
<h1>{data.name}</h1>
|
||||||
<p>{data.description}</p>
|
<p>{data.description}</p>
|
||||||
<ServiceRatingSummary serviceId={data.id} variant="row" showOpinionCount={false} />
|
<ServiceRatingSummary
|
||||||
|
serviceId={data.id}
|
||||||
|
variant="row"
|
||||||
|
showOpinionCount={false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.serviceActions}>
|
<div className={style.serviceActions}>
|
||||||
<span className={style.servicePrice}>{formatPrice(data.price)}</span>
|
<span className={style.servicePrice}>{formatPrice(data.price)}</span>
|
||||||
@@ -159,8 +171,21 @@ export default function Org() {
|
|||||||
<div style={{ marginBottom: "20px" }}> </div>
|
<div style={{ marginBottom: "20px" }}> </div>
|
||||||
|
|
||||||
{shareService && (
|
{shareService && (
|
||||||
<Dialog open={!!shareService} onClose={() => setShareService(null)} maxWidth="sm" fullWidth>
|
<Dialog
|
||||||
<DialogTitle sx={{ m: 0, p: 2, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
open={!!shareService}
|
||||||
|
onClose={() => setShareService(null)}
|
||||||
|
maxWidth="sm"
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<DialogTitle
|
||||||
|
sx={{
|
||||||
|
m: 0,
|
||||||
|
p: 2,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<span style={{ fontWeight: "bold" }}>Compartir Servicio</span>
|
<span style={{ fontWeight: "bold" }}>Compartir Servicio</span>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
@@ -171,23 +196,57 @@ export default function Org() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<div style={{ textAlign: "center", marginBottom: "30px", fontSize: "16px", color: "var(--black-light)" }}>
|
<div
|
||||||
Compartí tu servicio <strong>{shareService.name}</strong> para que tus clientes puedan reservarlo directamente.
|
style={{
|
||||||
|
textAlign: "center",
|
||||||
|
marginBottom: "30px",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: "var(--black-light)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Compartí tu servicio <strong>{shareService.name}</strong> para que tus
|
||||||
|
clientes puedan reservarlo directamente.
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", justifyContent: "center", flexDirection: "row", alignItems: "center", gap: "20px", paddingBottom: "20px" }}>
|
<div
|
||||||
<WhatsappShareButton title={"Reserva este servicio: " + shareService.name} separator=":: " url={window.location.origin + "/landing/service/" + shareService.id}>
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "20px",
|
||||||
|
paddingBottom: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<WhatsappShareButton
|
||||||
|
title={"Reserva este servicio: " + shareService.name}
|
||||||
|
separator=":: "
|
||||||
|
url={window.location.origin + "/landing/service/" + shareService.id}
|
||||||
|
>
|
||||||
<WhatsAppShareIcon size={54} round />
|
<WhatsAppShareIcon size={54} round />
|
||||||
</WhatsappShareButton>
|
</WhatsappShareButton>
|
||||||
<FacebookShareButton title={"Reserva este servicio: " + shareService.name} url={window.location.origin + "/landing/service/" + shareService.id}>
|
<FacebookShareButton
|
||||||
|
title={"Reserva este servicio: " + shareService.name}
|
||||||
|
url={window.location.origin + "/landing/service/" + shareService.id}
|
||||||
|
>
|
||||||
<FacebookIcon size={54} round />
|
<FacebookIcon size={54} round />
|
||||||
</FacebookShareButton>
|
</FacebookShareButton>
|
||||||
<EmailShareButton title={"Reserva este servicio: " + shareService.name} separator=":: " url={window.location.origin + "/landing/service/" + shareService.id}>
|
<EmailShareButton
|
||||||
|
title={"Reserva este servicio: " + shareService.name}
|
||||||
|
separator=":: "
|
||||||
|
url={window.location.origin + "/landing/service/" + shareService.id}
|
||||||
|
>
|
||||||
<EmailIcon size={54} round />
|
<EmailIcon size={54} round />
|
||||||
</EmailShareButton>
|
</EmailShareButton>
|
||||||
<TelegramShareButton title={"Reserva este servicio: " + shareService.name} url={window.location.origin + "/landing/service/" + shareService.id}>
|
<TelegramShareButton
|
||||||
|
title={"Reserva este servicio: " + shareService.name}
|
||||||
|
url={window.location.origin + "/landing/service/" + shareService.id}
|
||||||
|
>
|
||||||
<TelegramIcon size={54} round />
|
<TelegramIcon size={54} round />
|
||||||
</TelegramShareButton>
|
</TelegramShareButton>
|
||||||
<TwitterShareButton title={"Reserva este servicio: " + shareService.name} url={window.location.origin + "/landing/service/" + shareService.id}>
|
<TwitterShareButton
|
||||||
|
title={"Reserva este servicio: " + shareService.name}
|
||||||
|
url={window.location.origin + "/landing/service/" + shareService.id}
|
||||||
|
>
|
||||||
<TwitterIcon size={54} round />
|
<TwitterIcon size={54} round />
|
||||||
</TwitterShareButton>
|
</TwitterShareButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+3
-3
@@ -54,7 +54,7 @@ export default function TemplateCreate() {
|
|||||||
|
|
||||||
const insertAtCursor = (
|
const insertAtCursor = (
|
||||||
ref: React.RefObject<HTMLInputElement | HTMLTextAreaElement>,
|
ref: React.RefObject<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
insertText: string
|
insertText: string,
|
||||||
) => {
|
) => {
|
||||||
const el = ref.current;
|
const el = ref.current;
|
||||||
if (!el) return; // todavía no está montado
|
if (!el) return; // todavía no está montado
|
||||||
@@ -126,14 +126,14 @@ export default function TemplateCreate() {
|
|||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Eliminar
|
Eliminar
|
||||||
</ButtonMaterial>
|
</ButtonMaterial>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
|
|
||||||
loadTemplate();
|
loadTemplate();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from "@models/Templates.model";
|
} from "@models/Templates.model";
|
||||||
import { findTemplatesByOrganization } from "./Templates.Service";
|
import { findTemplatesByOrganization } from "./Templates.Service";
|
||||||
import { useNavigation } from "@core/app/hooks/goto";
|
import { useNavigation } from "@core/app/hooks/goto";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -29,6 +30,7 @@ export default function TemplatesGrid() {
|
|||||||
const oid = data.id;
|
const oid = data.id;
|
||||||
const { goTo } = useNavigation();
|
const { goTo } = useNavigation();
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
|
|
||||||
const formatType = (type: string) => {
|
const formatType = (type: string) => {
|
||||||
@@ -91,8 +93,8 @@ export default function TemplatesGrid() {
|
|||||||
parseInt(
|
parseInt(
|
||||||
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
? process.env.NEXT_PUBLIC_DATAGRID_PAGE_SIZE
|
||||||
: "10"
|
: "10",
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
const [templates, setTemplates] = useState<PaginateTemplatesResults>();
|
const [templates, setTemplates] = useState<PaginateTemplatesResults>();
|
||||||
|
|
||||||
@@ -103,6 +105,8 @@ export default function TemplatesGrid() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Mis organizaciones",
|
title: "Mis organizaciones",
|
||||||
@@ -122,6 +126,10 @@ export default function TemplatesGrid() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadTemplates(1, pageSize);
|
loadTemplates(1, pageSize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadTemplates = (page: number = 1, pageSize: number = 30) => {
|
const loadTemplates = (page: number = 1, pageSize: number = 30) => {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import Image from "next/image";
|
|||||||
import Switch from "@core/app/components/Switch/Switch";
|
import Switch from "@core/app/components/Switch/Switch";
|
||||||
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
import { useConfirmStore } from "@core/Store/Confirm.Store";
|
||||||
import SecureByPlan, { SECURE_CONTENTS } from "@core/app/components/SecureByPlan/SecureByPlan";
|
import SecureByPlan, { SECURE_CONTENTS } from "@core/app/components/SecureByPlan/SecureByPlan";
|
||||||
|
import { useBottomToolbarStore } from "@core/Store/BottomToolbar.Store";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -35,6 +36,7 @@ export default function OrganizationEdit() {
|
|||||||
const data = useParams<UrlData>();
|
const data = useParams<UrlData>();
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const location = useLocationStore();
|
const location = useLocationStore();
|
||||||
|
const bottomToolbar = useBottomToolbarStore();
|
||||||
const eventHandler = useEventHandlerStore();
|
const eventHandler = useEventHandlerStore();
|
||||||
const SessionInfo = useSessionStore();
|
const SessionInfo = useSessionStore();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@@ -46,6 +48,8 @@ export default function OrganizationEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
location.clear();
|
location.clear();
|
||||||
|
|
||||||
|
bottomToolbar.set(<></>);
|
||||||
|
|
||||||
location.add({
|
location.add({
|
||||||
url: "/admin/org",
|
url: "/admin/org",
|
||||||
title: "Organizaciones",
|
title: "Organizaciones",
|
||||||
@@ -63,6 +67,10 @@ export default function OrganizationEdit() {
|
|||||||
title: "Whatsapp",
|
title: "Whatsapp",
|
||||||
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
icon: <OrgConfigIcon sx={{ fontSize: "32px", mr: "10px" }} />,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
bottomToolbar.clear();
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -420,7 +428,7 @@ export default function OrganizationEdit() {
|
|||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
() => { }
|
() => {},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user