first commit
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { PendingRepeatView } from "@core/Models/Repeats.model";
|
||||
import { getPendingRepeatsCurrentWeek } from "../../admin/(client-profile)/org/[oid]/client/[clientId]/Client.Service";
|
||||
import { createAppointment } from "../../admin/(organization-profile)/org/profile/[id]/appointments/[appdate]/Appointment.Service";
|
||||
import { useSessionStore } from "@core/Store/Sesion.Store";
|
||||
import { useAlert } from "@core/Store/Alert.Store";
|
||||
import { EVENT_TYPES, useEventHandlerStore } from "@core/Store/EventHandler.Store";
|
||||
import dayjs from "dayjs";
|
||||
import Button from "../Button/Button";
|
||||
import { ThemeProvider } from "@emotion/react";
|
||||
import turnosXpressTheme from "@core/app/theme/turnosXpress";
|
||||
import style from "./style.module.css";
|
||||
import { Box, Typography, Card, CardContent, Checkbox } from "@mui/material";
|
||||
|
||||
interface PendingRepeatsCardProps {
|
||||
companyId?: string;
|
||||
employeeId?: string; // Optional filter
|
||||
allowEmployeeFilter?: boolean;
|
||||
}
|
||||
|
||||
const PendingRepeatsCard: React.FC<PendingRepeatsCardProps> = ({ companyId, employeeId, allowEmployeeFilter }) => {
|
||||
const SessionInfo = useSessionStore();
|
||||
const alert = useAlert();
|
||||
const eventHandler = useEventHandlerStore();
|
||||
const [pendingRepeats, setPendingRepeats] = useState<PendingRepeatView[]>([]);
|
||||
const [filterByMe, setFilterByMe] = useState<boolean>(false);
|
||||
|
||||
const loadRepeats = () => {
|
||||
if (!SessionInfo.userId) return;
|
||||
|
||||
const isGlobalView = !companyId;
|
||||
const isFilterByMeActive = isGlobalView || (allowEmployeeFilter && filterByMe);
|
||||
|
||||
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
||||
getPendingRepeatsCurrentWeek({
|
||||
companyId,
|
||||
employeeId,
|
||||
sessionUser: SessionInfo.userId,
|
||||
filterBySessionUser: isFilterByMeActive
|
||||
}).then(res => {
|
||||
setPendingRepeats(res);
|
||||
}).catch(err => {
|
||||
alert.showError(err.message || "Error al cargar repeticiones pendientes");
|
||||
}).finally(() => {
|
||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadRepeats();
|
||||
}, [companyId, employeeId, SessionInfo.userId, filterByMe, allowEmployeeFilter]);
|
||||
|
||||
const handleCreateAppointment = (repeat: PendingRepeatView) => {
|
||||
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
||||
createAppointment({
|
||||
companyId: String(repeat.companyId),
|
||||
serviceId: String(repeat.serviceId),
|
||||
employeeId: String(repeat.employeeId),
|
||||
clientId: String(repeat.clientId),
|
||||
repeatId: repeat.id,
|
||||
start: dayjs(repeat.pendingDate).toISOString(),
|
||||
notification: false,
|
||||
validation: false,
|
||||
sessionUser: SessionInfo.userId,
|
||||
}).then(() => {
|
||||
alert.showSuccess("Turno creado con éxito");
|
||||
loadRepeats(); // Refresh the list
|
||||
}).catch(err => {
|
||||
alert.showError(err.format ? err.format() : err.message);
|
||||
}).finally(() => {
|
||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||
});
|
||||
};
|
||||
|
||||
if (pendingRepeats.length === 0 && !filterByMe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={turnosXpressTheme}>
|
||||
<Box className={style.container}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||||
<Typography variant="h6" className={style.title} sx={{ mb: 0 }}>
|
||||
Turnos recurrentes pendientes de creación (Semana Actual)
|
||||
</Typography>
|
||||
{(allowEmployeeFilter && companyId) && (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
||||
Solo mis turnos
|
||||
</Typography>
|
||||
<Checkbox
|
||||
checked={filterByMe}
|
||||
onChange={(e) => setFilterByMe(e.target.checked)}
|
||||
color="primary"
|
||||
size="small"
|
||||
sx={{ padding: 0 }}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{pendingRepeats.length === 0 ? (
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary', p: 2 }}>
|
||||
No hay turnos recurrentes pendientes.
|
||||
</Typography>
|
||||
) : (
|
||||
<div className={style.grid}>
|
||||
{pendingRepeats.map(repeat => (
|
||||
<Card key={repeat.id} className={style.card}>
|
||||
<CardContent>
|
||||
<Typography variant="subtitle1" fontWeight="bold">
|
||||
{repeat.clientName}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{repeat.serviceName} con {repeat.employeeName}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ mt: 1, color: "var(--wine-red)", fontWeight: "bold" }}>
|
||||
{dayjs(repeat.pendingDate).format("dddd DD/MM HH:mm")} hs.
|
||||
</Typography>
|
||||
<Box sx={{ mt: 2, display: "flex", justifyContent: "flex-end" }}>
|
||||
<Button
|
||||
text="Crear Turno"
|
||||
color="primary"
|
||||
onClick={() => handleCreateAppointment(repeat)}
|
||||
/>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default PendingRepeatsCard;
|
||||
@@ -0,0 +1,26 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
background-color: #fff9fa;
|
||||
border: 1px solid var(--wine-red);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--wine-red);
|
||||
margin-bottom: 16px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 8px !important;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05) !important;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
Reference in New Issue
Block a user