import { useState } from "react"; import { Buffer } from "buffer"; import { v4 as uuidv4 } from "uuid"; /** * constants */ //const wssProtocol = window.location.protocol === "https:" ? "wss://" : "ws://"; let apiAddress = ""; // let staticContentAddress = ""; // let wsAddress = ""; if (window.location.hostname === "localhost" && window.location.port === "") { // for docker container testing on localhost apiAddress = "http://localhost/api/v1"; // staticContentAddress = "http://localhost/api/"; // wsAddress = "ws://localhost/ws"; } else if (window.location.hostname === "localhost") { // programming on localhost apiAddress = "http://localhost:50128/api/v1"; // staticContentAddress = "http://localhost:50050/"; // wsAddress = "ws://localhost:50050/ws"; } else { // production apiAddress = `${window.location.protocol}//${window.location.hostname}/api/v1`; //staticContentAddress = `${window.location.protocol}//${window.location.hostname}/api/`; // wsAddress = `${wssProtocol}${window.location.hostname}/ws`; } export const Constants = { TEXT_EMPTY_PLACEHOLDER: "-/-", API_ADDRESS: apiAddress, //STATIC_CONTENT_ADDRESS: staticContentAddress, // WS_ADDRESS: wsAddress, EMBED_CALENDAR_ADDRESS: "https://calendar.ex.umbach.dev/embed/?id=", ROUTE_PATHS: { OVERVIEW: "/", STORE: { SETTINGS: "/store/settings", EMPLOYEES: "/store/employees", SERVICES: "/store/services", CALENDAR: "/store/calendar", CALENDAR_AUTH: "/store/calendar/auth", WEBSITE: "/store/website", }, FEEDBACK: "/feedback", SUPPORT: "/support", USER_PROFILE: "/user-profile", }, GLOBALS: { MIN_USERNAME_LENGTH: 3, MAX_USERNAME_LENGTH: 20, MIN_ACCOUNT_NAME_LENGTH: 3, MAX_ACCOUNT_NAME_LENGTH: 20, MIN_PASSWORD_LENGTH: 8, MAX_PASSWORD_LENGTH: 64, MIN_STORE_SERVICE_NAME_LENGTH: 3, MAX_STORE_SERVICE_NAME_LENGTH: 64, MIN_STORE_SERVICE_ACTIVITY_NAME_LENGTH: 3, MAX_STORE_SERVICE_ACTIVITY_NAME_LENGTH: 64, MIN_STORE_SERVICE_ACTIVITY_DESCRIPTION_LENGTH: 3, MAX_STORE_SERVICE_ACTIVITY_DESCRIPTION_LENGTH: 1024, MIN_STORE_SERVICE_ACTIVITY_PRICE: 0, MAX_STORE_SERVICE_ACTIVITY_PRICE: 10000000, MIN_STORE_SERVICE_ACTIVITY_DURATION_MINUTES: 0, MAX_STORE_SERVICE_ACTIVITY_DURATION_MINUTES: 60 * 24, // 24 hours in minutes MIN_CALENDAR_FUTURE_BOOKING_DAYS: 0, MAX_CALENDAR_FUTURE_BOOKING_DAYS: 365, MIN_CALENDAR_EARLIEST_BOOKING_TIME: 0, MAX_CALENDAR_EARLIEST_BOOKING_TIME: 60 * 24, // 24 hours in minutes }, DELAY_ACCOUNT_NAME_CHECK: 250, }; export const AppStyle = { app: { margin: 12, }, }; export function GetUuid() { return uuidv4(); } /** * user session */ export function UseUserSession() { const getUserSession = () => { return getUserSessionFromLocalStorage(); }; const [userSession, setUserSession] = useState(getUserSession()); const saveUserSession = (session) => { setUserSession(session); if (session === undefined) { localStorage.removeItem("session"); } else { setUserSessionToLocalStorage(session); } }; return { setUserSession: saveUserSession, userSession, }; } export function getUserSessionFromLocalStorage() { return localStorage.getItem("session"); } export function setUserSessionToLocalStorage(session) { localStorage.setItem("session", session); } // needed for a user who uses multiple tabs in the browser // with the same session id because otherwise the last browser // tab would subscribe to the topic and the other tabs would // not receive any messages // used for topic subscribtion and grouptasks export const BrowserTabSession = GetUuid(); export const wsConnectionCustomEventName = "wsConnection"; // used for sideMenu export const BreakpointLgWidth = 992; export function EncodeStringToBase64(value) { return Buffer.from(value).toString("base64"); } export function DecodedBase64ToString(value) { return Buffer.from(value, "base64").toString(); } export const myFetchContentType = { JSON: 0, MULTIPART_FORM_DATA: 1, }; export function myFetch({ url, method, body = null, headers = {}, contentType = myFetchContentType.JSON, fetchUrl = Constants.API_ADDRESS, ignoreUnauthorized = false, notificationApi = null, t = null, }) { const getContentType = () => { if (contentType === myFetchContentType.JSON) return "application/json"; return "multipart/form-data"; }; const getBody = () => { if (!body) return null; if (contentType === myFetchContentType.JSON) return JSON.stringify(body); return body; }; // abort fetch if it takes to long const controller = new AbortController(); const signal = controller.signal; setTimeout(() => controller.abort(), 30000); // 30 seconds const requestOptions = { method: method, headers: { "X-Authorization": getUserSessionFromLocalStorage(), "Content-Type": getContentType(), ...headers, }, body: getBody(), signal: signal, }; if (fetchUrl === "") { fetchUrl = Constants.API_ADDRESS; } return fetch(`${fetchUrl}${url}`, requestOptions) .then((response) => { // if status is not in range 200-299 if (!response.ok) { if (!ignoreUnauthorized && response.status === 401) { console.error("Unauthorized"); // TODO: check here //setUserSessionToLocalStorage(""); //window.location.href = "/"; } throw response.status; } // check if response is json if (response.headers.get("content-type")?.includes("application/json")) { return response.json(); } return response.text(); }) .catch((error) => { // ignore errors here as they are handled in the components if (error === 400 || error === 401) throw error; // show error notification for all other errors if (notificationApi !== null && t !== null) { if (error === 500) { notificationApi["error"]({ message: t("common.request.failed.title"), description: t("common.request.failed.description"), }); } else { // other errors notificationApi["error"]({ message: t("common.request.failedInternetProblem.title"), description: t("common.request.failedInternetProblem.description"), }); } } throw error; }); } export function isDevelopmentEnv() { return process.env.NODE_ENV === "development"; } export function showInputsInvalidNotification(notificationApi, t) { notificationApi["error"]({ message: t("common.request.inputsInvalid.title"), description: t("common.request.inputsInvalid.description"), }); }