first commit

This commit is contained in:
2026-07-16 20:48:43 -03:00
commit 5696cee264
1111 changed files with 322270 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
import { create } from "zustand";
export enum ALERT_MODES {
SUCCESS = "success",
ERROR = "error",
WARNING = "warning",
INFO = "info",
}
interface IAlertStore {
visible: boolean;
message: string;
mode: ALERT_MODES;
hiddingTimeout: number;
setVisible: (state: boolean) => void;
showSuccess: (message: string) => void;
showError: (message: string) => void;
showWarning: (message: string) => void;
showInfo: (message: string) => void;
clear: () => void;
}
export type AlertState = IAlertStore;
const useAlert = create<AlertState>()((set) => ({
visible: false,
message: "",
mode: ALERT_MODES.SUCCESS,
hiddingTimeout: 6000,
setVisible: (state: boolean) => set(() => ({ visible: state })),
showSuccess: (message: string) =>
set(() => ({
message: message,
visible: true,
mode: ALERT_MODES.SUCCESS,
hiddingTimeout: 1000,
})),
showError: (message: string) =>
set(() => ({
message: message,
visible: true,
mode: ALERT_MODES.ERROR,
hiddingTimeout: 6000,
})),
showWarning: (message: string) =>
set(() => ({
message: message,
visible: true,
mode: ALERT_MODES.WARNING,
hiddingTimeout: 6000,
})),
showInfo: (message: string) =>
set(() => ({
message: message,
visible: true,
mode: ALERT_MODES.INFO,
hiddingTimeout: 6000,
})),
clear: () =>
set(() => ({
visible: false,
message: "",
mode: ALERT_MODES.SUCCESS,
hiddingTimeout: 6000,
})),
}));
export { useAlert };
@@ -0,0 +1,20 @@
import { create } from "zustand";
interface IAppointmentsViewStore {
collaboratorId: string;
setCollaboratorId: (id: string) => void;
clear: () => void;
}
export type AppointmentsState = IAppointmentsViewStore;
const useAppointmentsViewStore = create<AppointmentsState>()((set) => ({
collaboratorId: "",
setCollaboratorId: (id: string) => set(() => ({ collaboratorId: id })),
clear: () =>
set(() => ({
collaboratorId: "",
})),
}));
export { useAppointmentsViewStore };
+21
View File
@@ -0,0 +1,21 @@
import React from "react";
import { create } from "zustand";
interface IBottomToolbarStore {
toolbar: React.ReactNode;
set: (item: React.ReactNode) => void;
clear: () => void;
}
export type BottomToolbarState = IBottomToolbarStore;
const useBottomToolbarStore = create<BottomToolbarState>()((set) => ({
toolbar: undefined,
set: (item: React.ReactNode) => set(() => ({ toolbar: item })),
clear: () =>
set(() => ({
toolbar: undefined,
})),
}));
export { useBottomToolbarStore };
+26
View File
@@ -0,0 +1,26 @@
import { persist, createJSONStorage } from "zustand/middleware";
import { create } from "zustand";
export type ButtonPanelMode = "icon" | "button";
export interface ILoginActionStore {
mode: ButtonPanelMode;
setMode: (mod: ButtonPanelMode) => void;
clear: () => void;
}
const useButtonPanelStore = create<ILoginActionStore>()(
persist(
(set) => ({
mode: "button",
setMode: (mod: ButtonPanelMode) => set(() => ({ mode: mod })),
clear: () => set(() => ({ mode: "button" })),
}),
{
name: "site-panel-mode",
storage: createJSONStorage(() => localStorage),
}
)
);
export { useButtonPanelStore };
+24
View File
@@ -0,0 +1,24 @@
import { create } from "zustand";
import { TXCalendarEvent } from "@core/app/theme/scheduleView";
interface IClipboardStore {
copiedAppointment: TXCalendarEvent | null;
setCopiedAppointment: (event: TXCalendarEvent | null) => void;
clear: () => void;
}
export type ClipboardState = IClipboardStore;
const useClipboardStore = create<ClipboardState>()((set) => ({
copiedAppointment: null,
setCopiedAppointment: (event: TXCalendarEvent | null) =>
set(() => ({
copiedAppointment: event,
})),
clear: () =>
set(() => ({
copiedAppointment: null,
})),
}));
export { useClipboardStore };
+48
View File
@@ -0,0 +1,48 @@
import { create } from "zustand";
interface IConfirmStore {
visible: boolean;
message: string;
title: string;
onConfirm: () => void;
onCancel: () => void;
show: (message: string, onConfirm: () => void, onCancel: () => void) => void;
close: () => void;
clear: () => void;
}
export type ConfirmState = IConfirmStore;
const useConfirmStore = create<ConfirmState>()((set) => ({
visible: false,
message: "",
title: "",
onConfirm: () => {},
onCancel: () => {},
show: (message: string, onConfirm: () => void, onCancel: () => void) =>
set(() => ({
visible: true,
message: message,
onConfirm: onConfirm,
onCancel: onCancel,
title: "Atención",
})),
close: () =>
set(() => ({
visible: false,
message: "",
onConfirm: () => {},
onCancel: () => {},
title: "",
})),
clear: () =>
set(() => ({
visible: false,
message: "",
onConfirm: () => {},
onCancel: () => {},
title: "",
})),
}));
export { useConfirmStore };
+31
View File
@@ -0,0 +1,31 @@
import { create } from "zustand";
export enum EVENT_TYPES {
SAVE = "save",
ADD = "add",
CLEAR = "clear",
FILTER = "filter",
SLEEP = "sleep",
NEED_SAVE = "need-save",
NEED_ADD = "need-add",
LOADING = "loading",
}
interface IEventHandlerStore {
eventType: EVENT_TYPES;
setEventType: (state: EVENT_TYPES) => void;
clear: () => void;
}
export type EventHandlerState = IEventHandlerStore;
const useEventHandlerStore = create<EventHandlerState>()((set) => ({
eventType: EVENT_TYPES.SLEEP,
setEventType: (state: EVENT_TYPES) => set(() => ({ eventType: state })),
clear: () =>
set(() => ({
eventType: EVENT_TYPES.SLEEP,
})),
}));
export { useEventHandlerStore };
+49
View File
@@ -0,0 +1,49 @@
import React from "react";
import { create } from "zustand";
export interface FilterData {
id?: string;
}
interface IFilterStore {
filter: React.ReactNode;
visible: boolean;
title: string;
filterData: FilterData;
onFilter: () => void;
setContent: (item: React.ReactNode) => void;
setOnFilter: (onFilter: () => void) => void;
setVisible: (state: boolean) => void;
setTitle: (title: string) => void;
setFilterData: (data: FilterData) => void;
toggle: () => void;
clear: () => void;
clearFilterData: () => void;
}
export type FilterState = IFilterStore;
const useFilterStore = create<FilterState>()((set) => ({
filter: undefined,
visible: false,
title: "",
filterData: {},
onFilter: () => {},
setOnFilter: (onFilter: () => void) => set(() => ({ onFilter })),
setContent: (item: React.ReactNode) => set(() => ({ filter: item })),
setVisible: (state: boolean) => set(() => ({ visible: state })),
setTitle: (title: string) => set(() => ({ title: title })),
setFilterData: (data: FilterData) => set(() => ({ filterData: data })),
toggle: () => set((state) => ({ visible: !state.visible })),
clear: () =>
set(() => ({
filter: undefined,
visible: false,
title: "",
onFilter: () => {},
filterData: {},
})),
clearFilterData: () => set(() => ({ filterData: {} })),
}));
export { useFilterStore };
+62
View File
@@ -0,0 +1,62 @@
import { NO_CATEGORY } from "@core/Models/Categories.type";
import { create } from "zustand";
export enum HEADER_MODES {
LARGE = "large",
SMALL = "small",
}
export enum HEADER_WIDGETS {
FIND = "find",
PUBLIC_FIND = "public-find",
NONE = "none",
}
interface IHeaderStore {
notificationsCount: number;
state: HEADER_MODES;
activeWidget: HEADER_WIDGETS;
findText: string;
publicFindText: string;
publicFindCategoryId: number;
publicFindTrigger: boolean;
setNotificationsCount: (count: number) => void;
setState: (state: HEADER_MODES) => void;
setFindText: (text: string) => void;
setPublicFindText: (text: string) => void;
setPublicFindCategoryId: (id: number) => void;
setActiveWidget: (widget: HEADER_WIDGETS) => void;
setPublicFindTrigger: (trigger: boolean) => void;
clear: () => void;
}
export type HeaderState = IHeaderStore;
const useHeaderStore = create<HeaderState>()((set) => ({
notificationsCount: 0,
state: HEADER_MODES.LARGE,
activeWidget: HEADER_WIDGETS.PUBLIC_FIND,
findText: "",
publicFindText: "",
publicFindCategoryId: NO_CATEGORY,
publicFindTrigger: false,
setNotificationsCount: (count: number) => set(() => ({ notificationsCount: count })),
setState: (state: HEADER_MODES) => set(() => ({ state: state })),
setFindText: (text: string) => set(() => ({ findText: text })),
setPublicFindText: (text: string) => set(() => ({ publicFindText: text })),
setPublicFindCategoryId: (id: number) => set(() => ({ publicFindCategoryId: id })),
setActiveWidget: (widget: HEADER_WIDGETS) => set(() => ({ activeWidget: widget })),
setPublicFindTrigger: (trigger: boolean) => set(() => ({ publicFindTrigger: trigger })),
clear: () =>
set(() => ({
notificationsCount: 0,
state: HEADER_MODES.LARGE,
activeWidget: HEADER_WIDGETS.PUBLIC_FIND,
findText: "",
publicFindText: "",
publicFindCategoryId: NO_CATEGORY,
publicFindTrigger: false,
})),
}));
export { useHeaderStore };
+31
View File
@@ -0,0 +1,31 @@
import { create } from "zustand";
export type LocationItem = {
url: string;
title: string;
icon?: React.ReactNode;
};
interface ILocationStore {
path: LocationItem[];
add: (item: LocationItem) => void;
last: () => LocationItem | undefined;
clear: () => void;
}
export type LocationState = ILocationStore;
const useLocationStore = create<LocationState>()((set, get) => ({
path: [],
add: (item: LocationItem) => set((state) => ({ path: [...state.path, item] })),
last: () => {
const path = get().path;
return path.length - 1 >= 0 ? path[path.length - 1] : undefined; // Retorna el último elemento o `undefined` si el array está vacío
},
clear: () =>
set(() => ({
path: [],
})),
}));
export { useLocationStore };
+35
View File
@@ -0,0 +1,35 @@
import { persist, createJSONStorage } from "zustand/middleware";
import { create } from "zustand";
export enum LOGIN_ACTIONS {
PLAN_SUBSCRIPTION = "plan-subscription",
ORGANIZATION_CREATE = "organization-create",
APPOINTMENT_CREATE = "appointment-create",
NONE = "none",
}
export interface ILoginActionStore {
action: LOGIN_ACTIONS;
url: string;
setUrl: (url: string) => void;
setLoginAction: (action: LOGIN_ACTIONS) => void;
clear: () => void;
}
const useLoginActionStore = create<ILoginActionStore>()(
persist(
(set) => ({
action: LOGIN_ACTIONS.NONE,
url: "/",
setLoginAction: (action: LOGIN_ACTIONS) => set(() => ({ action: action })),
setUrl: (url: string) => set(() => ({ url: url })),
clear: () => set(() => ({ action: LOGIN_ACTIONS.NONE, url: "/" })),
}),
{
name: "site-login-action",
storage: createJSONStorage(() => localStorage),
}
)
);
export { useLoginActionStore };
+49
View File
@@ -0,0 +1,49 @@
import { create } from "zustand";
export type MenuItem = {
text?: string;
icon?: React.ReactNode;
onClick?: () => void;
divider?: boolean;
};
interface IMenuStore {
items: MenuItem[];
visible: boolean;
anchorEl: HTMLElement | null;
add: (item: MenuItem) => void;
setAnchorEl: (el: HTMLElement) => void;
divider: () => void;
show: () => void;
hide: () => void;
clear: () => void;
length: () => number;
}
export type MenuState = IMenuStore;
const useMenuStore = create<MenuState>()((set, get) => ({
items: [],
visible: false,
anchorEl: null,
add: (item: MenuItem) => set((state) => ({ items: [...state.items, item] })),
setAnchorEl: (el: HTMLElement) => set(() => ({ anchorEl: el })),
divider: () => set((state) => ({ items: [...state.items, { divider: true }] })),
show: () =>
set(() => ({
visible: true,
})),
hide: () =>
set(() => ({
visible: false,
})),
clear: () =>
set(() => ({
items: [],
visible: false,
})),
length: () => get().items.length,
}));
export { useMenuStore };
@@ -0,0 +1,20 @@
import { PublicOrganizationView } from "@core/Models/Company.model";
import { create } from "zustand";
export type LoginState = "started" | "success" | "sleep" | "error";
interface IOrgDataStore {
orgData: PublicOrganizationView | null;
setData: (data: PublicOrganizationView) => void;
clear: () => void;
}
const useOrgDataStore = create<IOrgDataStore>()((set) => ({
orgData: null,
setData: (data: PublicOrganizationView) => set(() => ({ orgData: data })),
clear: () =>
set(() => ({
orgData: null,
})),
}));
export { useOrgDataStore };
@@ -0,0 +1,56 @@
import { persist, createJSONStorage } from "zustand/middleware";
import { create } from "zustand";
export enum ORGANIZATION_HEADER_MODES {
LARGE = "large",
SMALL = "small",
}
interface IOrganizationHeaderStore {
state: ORGANIZATION_HEADER_MODES;
headerColor: string;
headerFontColor: string;
headerFontShadowColor: string;
setState: (state: ORGANIZATION_HEADER_MODES) => void;
setHeaderColor: (color: string) => void;
setHeaderFontColor: (color: string) => void;
setHeaderFontShadowColor: (color: string) => void;
toggleState: () => void;
clear: () => void;
}
export type OrganizationHeaderState = IOrganizationHeaderStore;
const useOrganizationHeaderStore = create<OrganizationHeaderState>()(
persist(
(set) => ({
state: ORGANIZATION_HEADER_MODES.LARGE,
headerColor: "",
headerFontColor: "",
headerFontShadowColor: "",
setState: (state: ORGANIZATION_HEADER_MODES) => set(() => ({ state: state })),
setHeaderColor: (color: string) => set(() => ({ headerColor: color })),
setHeaderFontColor: (color: string) => set(() => ({ headerFontColor: color })),
setHeaderFontShadowColor: (color: string) =>
set(() => ({ headerFontShadowColor: color })),
toggleState: () =>
set((state) => ({
state:
state.state === ORGANIZATION_HEADER_MODES.LARGE
? ORGANIZATION_HEADER_MODES.SMALL
: ORGANIZATION_HEADER_MODES.LARGE,
})),
clear: () =>
set(() => ({
state: ORGANIZATION_HEADER_MODES.LARGE,
})),
}),
{
name: "site-organization-header-state",
storage: createJSONStorage(() => localStorage),
}
)
);
export { useOrganizationHeaderStore };
+116
View File
@@ -0,0 +1,116 @@
import { ISession } from "@models/Session.model";
import { persist, createJSONStorage } from "zustand/middleware";
import ApiRequest from "@services/Api.Service";
import { create } from "zustand";
import { DefaultMetricsModel, IMetrics } from "@core/Models/Metrics.model";
import { DefaultSubscriptionModel, ISubscriptionInfo } from "@core/Models/Subscription.Model";
export type LoginState = "started" | "success" | "sleep" | "error";
interface ISessionStore {
loginState: LoginState;
loading: boolean;
setLoginState: (state: LoginState) => void;
setLoged: (state: boolean) => void;
setUserId: (userId: string) => void;
setUserFullName: (userFullName: string) => void;
setUserEmail: (userEmail: string) => void;
setUser: (sessionData: ISession) => void;
setSubscription: (subscription: ISubscriptionInfo) => void;
setMetrics: (metrics: IMetrics) => void;
checkSession: () => Promise<void>;
clear: () => void;
clearSubscription: () => void;
}
export type SessionState = ISession & ISessionStore;
const useSessionStore = create<SessionState>()((set) => ({
loged: false,
userId: "",
userName: "",
userFullName: "",
userEmail: "",
avatar: "",
subscription: DefaultSubscriptionModel,
organizationSubscriptions: {},
metrics: DefaultMetricsModel,
userToken: "",
loginState: "sleep",
loading: true,
setLoginState: (state: LoginState) => set(() => ({ loginState: state })),
setLoged: (state: boolean) => set(() => ({ loged: state })),
setUserId: (userId: string) => set(() => ({ userId: userId })),
setUserFullName: (userFullName: string) => set(() => ({ userFullName: userFullName })),
setUserEmail: (userEmail: string) => set(() => ({ userEmail: userEmail })),
setUser: (user: ISession) => set(() => ({ ...user })),
setSubscription: (subscription: ISubscriptionInfo) =>
set(() => ({ subscription: subscription })),
setMetrics: (metrics: IMetrics) => set(() => ({ metrics: metrics })),
checkSession: async () => {
const token = useSessionTokenStore.getState().token;
if (!token) {
set({ loading: false });
return;
}
try {
const sessionData = await ApiRequest.post<ISession>("users/loginbytoken", {
token,
});
set({ ...sessionData, loginState: "success" });
useSessionTokenStore.getState().setToken(sessionData.userToken);
} catch {
set({
loged: false,
loginState: "sleep",
userId: "",
userEmail: "",
userName: "",
userFullName: "",
avatar: "",
subscription: DefaultSubscriptionModel,
organizationSubscriptions: {},
metrics: DefaultMetricsModel,
});
useSessionTokenStore.getState().setToken("");
} finally {
set({ loading: false });
}
},
clear: () =>
set(() => ({
loged: false,
loginState: "sleep",
userId: "",
userEmail: "",
userName: "",
userFullName: "",
avatar: "",
subscription: DefaultSubscriptionModel,
organizationSubscriptions: {},
metrics: DefaultMetricsModel,
})),
clearSubscription: () => set(() => ({ subscription: DefaultSubscriptionModel })),
}));
export interface ISessionTokenStore {
token: string;
setToken: (token: string) => void;
}
const useSessionTokenStore = create<ISessionTokenStore>()(
persist(
(set) => ({
token: "",
setToken: (token: string) => set(() => ({ token: token })),
}),
{
name: "site-session-token",
storage: createJSONStorage(() => localStorage),
}
)
);
export { useSessionStore, useSessionTokenStore };
@@ -0,0 +1,51 @@
import { TextObjectFilterResult } from "@models/TextObjectFilter.model";
import { create } from "zustand";
export type TextObjectModalContent = {
header?: React.ReactNode;
bottom?: React.ReactNode;
renderResult: (result: TextObjectFilterResult, index: number) => React.ReactNode;
};
interface ITextObjectModalStore {
content: TextObjectModalContent;
data: TextObjectFilterResult[];
endpoint: string;
onSelected: (item: TextObjectFilterResult) => void;
setContent: (content: TextObjectModalContent) => void;
setData: (data: TextObjectFilterResult[]) => void;
setEndPoint: (endpoint: string) => void;
setOnSelected: (onSelected: (item: TextObjectFilterResult) => void) => void;
clear: () => void;
}
export type TextObjectModalState = ITextObjectModalStore;
const useTextObjectModalStore = create<TextObjectModalState>()((set) => ({
content: {
header: undefined,
bottom: undefined,
renderResult: () => undefined,
},
data: [],
endpoint: "",
onSelected: () => {},
setContent: (content: TextObjectModalContent) => set(() => ({ content: content })),
setData: (data: TextObjectFilterResult[]) => set(() => ({ data: data })),
setEndPoint: (endpoint: string) => set(() => ({ endpoint: endpoint })),
setOnSelected(onSelected: (item: TextObjectFilterResult) => void) {
set(() => ({ onSelected: onSelected }));
},
clear: () =>
set(() => ({
content: {
header: undefined,
bottom: undefined,
renderResult: () => undefined,
},
data: [],
endpoint: "",
})),
}));
export { useTextObjectModalStore };
+55
View File
@@ -0,0 +1,55 @@
import dayjs from "dayjs";
import "dayjs/locale/es";
import { create } from "zustand";
dayjs.locale("es");
interface ITimePickerStore {
visible: boolean;
timeFraction: number;
value: dayjs.Dayjs;
defaultValue: dayjs.Dayjs;
onAccept: (newDay: dayjs.Dayjs) => void;
setTimeFraction: (timeFraction: number) => void;
setValue: (value: dayjs.Dayjs) => void;
setDefaultValue: (value: dayjs.Dayjs) => void;
show: (onAccept: (newDay: dayjs.Dayjs) => void) => void;
hide: () => void;
}
export type TimePickerState = ITimePickerStore;
const useTimePickerStore = create<TimePickerState>()((set) => ({
visible: false,
timeFraction: 15,
value: dayjs(new Date()).hour(8).minute(0),
defaultValue: dayjs(new Date()),
onAccept: () => {},
setTimeFraction(timeFraction) {
set(() => ({
timeFraction: timeFraction,
}));
},
setDefaultValue(value) {
set(() => ({
defaultValue: value,
}));
},
setValue(value) {
set(() => ({
value: value,
}));
},
show: (onAccept: (newDay: dayjs.Dayjs) => void) =>
set(() => ({
visible: true,
onAccept: onAccept,
})),
hide: () =>
set(() => ({
visible: false,
onAccept: () => {},
})),
}));
export { useTimePickerStore };
+20
View File
@@ -0,0 +1,20 @@
import { create } from "zustand";
interface IUserMenuStore {
visible: boolean;
setVisible: (state: boolean) => void;
clear: () => void;
}
export type UserMenuState = IUserMenuStore;
const useUserMenuStore = create<UserMenuState>()((set) => ({
visible: false,
setVisible: (state: boolean) => set(() => ({ visible: state })),
clear: () =>
set(() => ({
visible: false,
})),
}));
export { useUserMenuStore };