diff --git a/resources/triptico/qrcode-tx-assistant.png b/resources/triptico/qrcode-tx-assistant.png new file mode 100644 index 0000000..676867d Binary files /dev/null and b/resources/triptico/qrcode-tx-assistant.png differ diff --git a/resources/triptico/qrcode-tx-login.png b/resources/triptico/qrcode-tx-login.png new file mode 100644 index 0000000..7118dae Binary files /dev/null and b/resources/triptico/qrcode-tx-login.png differ diff --git a/resources/triptico/qrcode-tx-plans.png b/resources/triptico/qrcode-tx-plans.png new file mode 100644 index 0000000..6c21b68 Binary files /dev/null and b/resources/triptico/qrcode-tx-plans.png differ diff --git a/resources/triptico/turnosxpress-triptico-interno.afdesign b/resources/triptico/turnosxpress-triptico-interno.afdesign index 1c2df5f..dd608ca 100644 Binary files a/resources/triptico/turnosxpress-triptico-interno.afdesign and b/resources/triptico/turnosxpress-triptico-interno.afdesign differ diff --git a/resources/triptico/turnosxpress-triptico.afdesign b/resources/triptico/turnosxpress-triptico.afdesign index feea326..548f721 100644 Binary files a/resources/triptico/turnosxpress-triptico.afdesign and b/resources/triptico/turnosxpress-triptico.afdesign differ diff --git a/server/src/Models/Appointments/Appointments.ts b/server/src/Models/Appointments/Appointments.ts index c801e42..81cfd86 100644 --- a/server/src/Models/Appointments/Appointments.ts +++ b/server/src/Models/Appointments/Appointments.ts @@ -534,7 +534,7 @@ class AppointmentManager implements IAppointmentsManager { await this.updateHeatMap(availabilityConfig); - await this.tryApplyDiscounts(newAppointment); + await this.tryApplyDiscounts(newAppointment, String(companyCheck.ownerId)); if (notification && checkClient.userId) { //Envio la notificacion al cliente. @@ -592,7 +592,7 @@ class AppointmentManager implements IAppointmentsManager { } } - private async tryApplyDiscounts(appointment: IAppointment) { + private async tryApplyDiscounts(appointment: IAppointment, sessionUser: string) { //Intenta aplicar un descuento al turno si esta especificado en DiscountsEmail // y la fecha coincide con el rango especificado. @@ -632,7 +632,7 @@ class AppointmentManager implements IAppointmentsManager { appointmentId: String(appointment.id), discountId: String(existDiscount.discountId), companyId: String(appointment.companyId), - sessionUser: String(appointment.userId), + sessionUser: sessionUser, }); } catch (err) { console.log(err); diff --git a/txclient/src/app/landing/dashboard/page.tsx b/txclient/src/app/landing/dashboard/page.tsx index a244e4f..6db8c95 100644 --- a/txclient/src/app/landing/dashboard/page.tsx +++ b/txclient/src/app/landing/dashboard/page.tsx @@ -41,6 +41,7 @@ import NotificationsNoneOutlinedIcon from "@mui/icons-material/NotificationsNone import ChatBubbleOutlineOutlinedIcon from "@mui/icons-material/ChatBubbleOutlineOutlined"; import AddCircleOutlineOutlinedIcon from "@mui/icons-material/AddCircleOutlineOutlined"; import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome"; +import HelpOutlineIcon from "@mui/icons-material/HelpOutline"; import FinancialWidget from "@components/FinancialWidget/FinancialWidget"; import PlanMetricsWidget from "@components/PlanMetricsWidget/PlanMetricsWidget"; import PendingRepeatsCard from "@core/app/components/PendingRepeatsCard/PendingRepeatsCard"; @@ -442,6 +443,9 @@ function DashboardContent() {
Nuevo Turno
+
goTo("/landing/help")}> + Obtener ayuda +
diff --git a/txclient/src/app/landing/dashboard/style.module.css b/txclient/src/app/landing/dashboard/style.module.css index f44cc87..728c40f 100644 --- a/txclient/src/app/landing/dashboard/style.module.css +++ b/txclient/src/app/landing/dashboard/style.module.css @@ -1,29 +1,42 @@ .dashboardGrid { display: grid; grid-template-columns: 1fr; - gap: 20px; + gap: 24px; width: 100%; - max-width: 1200px; - margin: 30px auto; - padding: 0 20px; + max-width: 1280px; + margin: 40px auto; + padding: 0 24px; } @media (min-width: 850px) { .dashboardGrid { - grid-template-columns: 350px 1fr; + grid-template-columns: 380px 1fr; } } +/* Welcome Card - Modern gradient design */ .welcomeCard { - background-color: white; - border-radius: 16px; - padding: 30px; - box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05); + background: linear-gradient(135deg, #ffffff 0%, #faf7fb 100%); + border-radius: 20px; + padding: 36px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.06); display: flex; flex-direction: column; - gap: 15px; + gap: 20px; grid-column: 1 / -1; position: relative; + border: 1px solid rgba(127, 42, 255, 0.08); + overflow: hidden; +} + +.welcomeCard::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 4px; + background: linear-gradient(90deg, var(--wine-red) 0%, var(--wine-dark) 50%, var(--wine-darkest) 100%); } .welcomeContainer { @@ -35,24 +48,35 @@ width: 100%; } +.welcomeContainer h3 { + font-size: 1.75rem; + font-weight: 800; + color: var(--wine-superdark); + margin: 0; + letter-spacing: -0.02em; +} + .metricsCard { background-color: white; - border-radius: 16px; + border-radius: 20px; padding: 30px; - box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.06); display: flex; flex-direction: column; gap: 20px; + border: 1px solid rgba(0, 0, 0, 0.04); } +/* Agenda Card */ .agendaCard { background-color: white; - border-radius: 16px; - padding: 30px; - box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05); + border-radius: 20px; + padding: 28px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.06); display: flex; flex-direction: column; - gap: 15px; + gap: 16px; + border: 1px solid rgba(0, 0, 0, 0.04); } .agendaHeader { @@ -68,10 +92,16 @@ text-align: left; } +.agendaHeader h3 { + font-size: 1.25rem; + font-weight: 700; + color: var(--wine-superdark); +} + .agendaHeaderTitleWrap { display: flex; align-items: center; - gap: 10px; + gap: 12px; min-width: 0; } @@ -79,14 +109,15 @@ display: inline-flex; align-items: center; justify-content: center; - min-width: 28px; - height: 28px; - padding: 0 9px; + min-width: 32px; + height: 32px; + padding: 0 10px; border-radius: 999px; - background: var(--wine-red); + background: linear-gradient(135deg, var(--wine-red) 0%, var(--wine-dark) 100%); color: var(--white); - font-size: 13px; - font-weight: 900; + font-size: 14px; + font-weight: 800; + box-shadow: 0 4px 12px rgba(255, 42, 127, 0.3); } .agendaToggleIcon { @@ -94,21 +125,27 @@ align-items: center; justify-content: center; flex: 0 0 auto; - width: 32px; - height: 32px; + width: 36px; + height: 36px; border-radius: 999px; background: var(--white); color: var(--wine-red); - border: 1px solid var(--wine-red); + border: 2px solid var(--wine-red); font-size: 22px; font-weight: 800; line-height: 1; + transition: all 0.2s ease; +} + +.agendaToggleIcon:hover { + background: var(--wine-red); + color: var(--white); } .agendaList { display: flex; flex-direction: column; - gap: 10px; + gap: 12px; max-height: 500px; overflow-y: auto; } @@ -116,22 +153,25 @@ .agendaItem { display: flex; flex-direction: column; - padding: 15px; - border-radius: 12px; - background-color: #f9f9f9; + padding: 16px 18px; + border-radius: 14px; + background: linear-gradient(135deg, #faf7fb 0%, #ffffff 100%); border-left: 4px solid var(--wine-red); - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: all 0.2s ease; + border: 1px solid rgba(127, 42, 255, 0.08); } .agendaItem:hover { transform: translateY(-2px); - box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.05); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); + border-left-color: var(--wine-dark); } +/* Quick Actions - Modern button grid */ .quickActions { display: grid; - grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); - gap: 15px; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 16px; } .actionButton { @@ -139,37 +179,75 @@ flex-direction: column; align-items: center; justify-content: center; - gap: 10px; - padding: 20px 10px; - border-radius: 16px; + gap: 12px; + padding: 24px 16px; + border-radius: 18px; color: white; - font-weight: bold; + font-weight: 700; cursor: pointer; - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); border: none; font-size: 14px; + position: relative; + overflow: hidden; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +.actionButton::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%); + opacity: 0; + transition: opacity 0.3s ease; +} + +.actionButton:hover::before { + opacity: 1; } .actionButton:hover { - transform: translateY(-4px); - box-shadow: 0px 6px 15px rgba(0, 0, 0, 0.1); + transform: translateY(-6px); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.15); } -.buttonOrganizations { background-color: var(--organization-card); } -.buttonNotification { background-color: var(--red); } -.buttonMessenger { background-color: var(--orange); } +.actionButton:active { + transform: translateY(-2px); +} +.actionButton svg { + font-size: 28px !important; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1)); +} + +.buttonOrganizations { + background: linear-gradient(135deg, var(--organization-card) 0%, var(--organization-flag) 100%); +} +.buttonNotification { + background: linear-gradient(135deg, var(--red) 0%, var(--red-darkest) 100%); +} +.buttonMessenger { + background: linear-gradient(135deg, var(--orange) 0%, #cc7a00 100%); +} +.buttonHelp { + background: linear-gradient(135deg, var(--wine-dark) 0%, var(--wine-darkest) 100%); +} + +/* Payment Cards */ .pendingPaymentCard { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 24px; - padding: 26px 30px; - border-radius: 18px; - background: #fff8e8; - border: 1px solid rgba(255, 151, 36, 0.28); - box-shadow: 0 12px 28px rgba(255, 151, 36, 0.1); + padding: 28px 32px; + border-radius: 20px; + background: linear-gradient(135deg, #fff8e8 0%, #fff3d6 100%); + border: 1px solid rgba(255, 151, 36, 0.3); + box-shadow: 0 12px 32px rgba(255, 151, 36, 0.12); } .failedPaymentCard { @@ -178,11 +256,11 @@ align-items: center; justify-content: space-between; gap: 24px; - padding: 26px 30px; - border-radius: 18px; - background: #f8fafc; - border: 1px solid rgba(100, 116, 139, 0.24); - box-shadow: 0 12px 28px rgba(15, 23, 42, 0.06); + padding: 28px 32px; + border-radius: 20px; + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + border: 1px solid rgba(100, 116, 139, 0.25); + box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08); } .expiredDowngradeCard { @@ -191,11 +269,11 @@ align-items: center; justify-content: space-between; gap: 24px; - padding: 26px 30px; - border-radius: 18px; - background: #fff7ed; - border: 1px solid rgba(194, 65, 12, 0.24); - box-shadow: 0 12px 28px rgba(194, 65, 12, 0.08); + padding: 28px 32px; + border-radius: 20px; + background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%); + border: 1px solid rgba(194, 65, 12, 0.25); + box-shadow: 0 12px 32px rgba(194, 65, 12, 0.1); color: #7c2d12; } @@ -210,78 +288,82 @@ .pendingPaymentContent { display: flex; flex-direction: column; - gap: 8px; + gap: 10px; max-width: 760px; } .pendingPaymentEyebrow { width: fit-content; - padding: 5px 11px; + padding: 6px 12px; border-radius: 999px; - background: rgba(255, 151, 36, 0.16); + background: rgba(255, 151, 36, 0.18); color: #9a4b00; font-size: 12px; - font-weight: 900; + font-weight: 800; text-transform: uppercase; - letter-spacing: 0.04em; + letter-spacing: 0.05em; } .failedPaymentEyebrow { width: fit-content; - padding: 5px 11px; + padding: 6px 12px; border-radius: 999px; - background: rgba(100, 116, 139, 0.12); + background: rgba(100, 116, 139, 0.14); color: #475569; font-size: 12px; - font-weight: 900; + font-weight: 800; text-transform: uppercase; - letter-spacing: 0.04em; + letter-spacing: 0.05em; } .expiredDowngradeEyebrow { width: fit-content; - padding: 5px 11px; + padding: 6px 12px; border-radius: 999px; - background: rgba(194, 65, 12, 0.12); + background: rgba(194, 65, 12, 0.14); color: #9a3412; font-size: 12px; - font-weight: 900; + font-weight: 800; text-transform: uppercase; - letter-spacing: 0.04em; + letter-spacing: 0.05em; } .expiredDowngradeButton { flex: 0 0 auto; - border: 1px solid rgba(124, 45, 18, 0.22); - border-radius: 14px; - background: #7c2d12; + border: 1px solid rgba(124, 45, 18, 0.25); + border-radius: 16px; + background: linear-gradient(135deg, #7c2d12 0%, #9a3412 100%); color: #fff7ed; cursor: pointer; - font-weight: 900; - padding: 14px 18px; - transition: transform 0.2s ease, box-shadow 0.2s ease; + font-weight: 800; + padding: 16px 20px; + transition: all 0.3s ease; + font-size: 15px; } .expiredDowngradeButton:hover { - box-shadow: 0 10px 24px rgba(124, 45, 18, 0.18); - transform: translateY(-2px); + box-shadow: 0 12px 28px rgba(124, 45, 18, 0.2); + transform: translateY(-3px); } .pendingPaymentContent h2 { margin: 0; color: var(--black); - font-size: clamp(22px, 3vw, 30px); + font-size: clamp(22px, 3vw, 28px); + font-weight: 800; + letter-spacing: -0.01em; } .pendingPaymentContent p { margin: 0; color: var(--gray-dark); - line-height: 1.55; + line-height: 1.6; + font-size: 15px; } .pendingPaymentLink { color: #9a4b00; - font-weight: 800; + font-weight: 700; text-decoration: underline; text-underline-offset: 3px; } @@ -295,31 +377,32 @@ min-width: 260px; } +/* Starter Cards */ .starterCard { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 24px; - padding: 32px; - border-radius: 20px; + padding: 36px; + border-radius: 24px; background: linear-gradient(135deg, rgba(128, 0, 32, 0.96), rgba(58, 0, 120, 0.94)); color: var(--white); - box-shadow: 0 18px 45px rgba(58, 0, 120, 0.18); + box-shadow: 0 20px 50px rgba(58, 0, 120, 0.2); } .starterContent { display: flex; flex-direction: column; - gap: 10px; + gap: 12px; max-width: 720px; } .starterEyebrow { width: fit-content; - padding: 6px 12px; + padding: 7px 14px; border-radius: 999px; - background: rgba(255, 255, 255, 0.16); + background: rgba(255, 255, 255, 0.18); font-size: 13px; font-weight: 800; text-transform: uppercase; @@ -329,14 +412,15 @@ .starterContent h2 { margin: 0; font-size: clamp(26px, 4vw, 38px); - line-height: 1.05; + line-height: 1.1; + font-weight: 800; } .starterContent p { margin: 0; - color: rgba(255, 255, 255, 0.86); + color: rgba(255, 255, 255, 0.88); font-size: 16px; - line-height: 1.6; + line-height: 1.65; } .starterActions { @@ -349,69 +433,79 @@ .starterPrimaryButton, .starterSecondaryButton { border: 0; - border-radius: 14px; - padding: 14px 18px; - font-weight: 900; + border-radius: 16px; + padding: 16px 20px; + font-weight: 800; cursor: pointer; - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: all 0.3s ease; + font-size: 15px; } .starterPrimaryButton:hover, .starterSecondaryButton:hover { - transform: translateY(-2px); + transform: translateY(-3px); } .starterPrimaryButton { background: var(--white); color: var(--wine-red); - box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); } .starterSecondaryButton { - background: rgba(255, 255, 255, 0.14); + background: rgba(255, 255, 255, 0.16); color: var(--white); - border: 1px solid rgba(255, 255, 255, 0.32); + border: 1px solid rgba(255, 255, 255, 0.35); } .starterGuideGrid { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 18px; + gap: 20px; } .starterGuideCard { min-height: 220px; - padding: 26px; - border-radius: 18px; + padding: 28px; + border-radius: 20px; background: var(--white); - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.06); + box-shadow: 0 12px 36px rgba(0, 0, 0, 0.07); border: 1px solid rgba(128, 0, 32, 0.08); + transition: all 0.3s ease; +} + +.starterGuideCard:hover { + transform: translateY(-4px); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.1); } .starterGuideNumber { display: inline-flex; align-items: center; justify-content: center; - width: 38px; - height: 38px; + width: 42px; + height: 42px; border-radius: 999px; - background: rgba(128, 0, 32, 0.1); - color: var(--wine-red); + background: linear-gradient(135deg, var(--wine-red) 0%, var(--wine-dark) 100%); + color: var(--white); font-weight: 900; - margin-bottom: 18px; + margin-bottom: 20px; + font-size: 18px; + box-shadow: 0 6px 16px rgba(255, 42, 127, 0.3); } .starterGuideCard h3 { - margin: 0 0 10px; + margin: 0 0 12px; color: var(--black); font-size: 20px; + font-weight: 700; } .starterGuideCard p { margin: 0; color: var(--gray-dark); - line-height: 1.55; + line-height: 1.6; font-size: 15px; } @@ -419,32 +513,34 @@ grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 420px); - gap: 28px; + gap: 32px; align-items: start; - padding: 34px; - border-radius: 20px; + padding: 36px; + border-radius: 24px; background: linear-gradient(180deg, #ffffff 0%, #faf7fb 100%); - box-shadow: 0 12px 34px rgba(0, 0, 0, 0.055); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.07); border: 1px solid rgba(128, 0, 32, 0.08); } .starterNextStepsPanel h3 { - margin: 14px 0 10px; + margin: 16px 0 12px; color: var(--black); font-size: clamp(24px, 3vw, 34px); + font-weight: 800; } .starterNextStepsPanel p { margin: 0; max-width: 680px; color: var(--gray-dark); - line-height: 1.65; + line-height: 1.7; + font-size: 15px; } .starterChecklist { display: flex; flex-direction: column; - gap: 14px; + gap: 16px; margin: 0; padding: 0; list-style: none; @@ -452,49 +548,81 @@ .starterChecklist li { position: relative; - padding: 14px 16px 14px 44px; - border-radius: 14px; + padding: 16px 18px 16px 48px; + border-radius: 16px; background: var(--white); color: var(--black); font-weight: 700; - box-shadow: 0 8px 18px rgba(0, 0, 0, 0.045); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.05); + border: 1px solid rgba(0, 0, 0, 0.04); + transition: all 0.2s ease; +} + +.starterChecklist li:hover { + transform: translateX(4px); + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08); } .starterChecklist li::before { content: "✓"; position: absolute; - left: 16px; + left: 18px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; - width: 20px; - height: 20px; + width: 22px; + height: 22px; border-radius: 999px; - background: var(--green); + background: linear-gradient(135deg, var(--green) 0%, var(--green-darkestX1) 100%); color: var(--white); font-size: 12px; font-weight: 900; + box-shadow: 0 3px 8px rgba(42, 255, 42, 0.3); } +/* Responsive */ @media (max-width: 760px) { + .dashboardGrid { + margin: 24px auto; + padding: 0 16px; + gap: 20px; + } + + .welcomeCard { + padding: 28px 24px; + } + + .welcomeContainer h3 { + font-size: 1.5rem; + } + + .quickActions { + grid-template-columns: repeat(2, 1fr); + gap: 12px; + } + + .actionButton { + padding: 20px 12px; + } + .pendingPaymentCard { align-items: stretch; flex-direction: column; - padding: 22px; + padding: 24px; } .failedPaymentCard { align-items: stretch; flex-direction: column; - padding: 22px; + padding: 24px; } .expiredDowngradeCard { align-items: stretch; flex-direction: column; - padding: 22px; + padding: 24px; } .expiredDowngradeButton { @@ -510,7 +638,7 @@ .starterCard { align-items: stretch; flex-direction: column; - padding: 24px; + padding: 28px; } .starterActions { @@ -523,7 +651,13 @@ .starterNextStepsPanel { grid-template-columns: 1fr; - padding: 24px; + padding: 28px; + } +} + +@media (max-width: 480px) { + .quickActions { + grid-template-columns: 1fr; } }