first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

55
bootstrap/app.php Executable file
View File

@@ -0,0 +1,55 @@
<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;

15
bootstrap/autoload.php Executable file
View File

@@ -0,0 +1,15 @@
<?php
/*
|--------------------------------------------------------------------------
| Register The Composer Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so we do not have to manually load any of
| our application's PHP classes. It just feels great to relax.
|
*/
require __DIR__ . '/../vendor/autoload.php';

2
bootstrap/cache/.gitignore vendored Executable file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -0,0 +1,60 @@
import { jsx } from "react/jsx-runtime";
import { c as createSvgIcon } from "../server-entry.mjs";
const LockOpenIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h2c0-1.66 1.34-3 3-3s3 1.34 3 3v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10zm-6-3c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z" }),
"LockOpenOutlined"
);
const ShareIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92s2.92-1.31 2.92-2.92c0-1.61-1.31-2.92-2.92-2.92zM18 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM6 13c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm12 7.02c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z" }),
"ShareOutlined"
);
const ExpandMoreIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z" }),
"ExpandMoreOutlined"
);
const CommentIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18zM20 4v13.17L18.83 16H4V4h16zM6 12h12v2H6zm0-3h12v2H6zm0-3h12v2H6z" }),
"CommentOutlined"
);
const ThumbUpIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M9 21h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.58 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2zM9 9l4.34-4.34L12 10h9v2l-3 7H9V9zM1 9h4v12H1z" }),
"ThumbUpOutlined"
);
const ThumbDownIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm0 12-4.34 4.34L12 14H3v-2l3-7h9v10zm4-12h4v12h-4z" }),
"ThumbDownOutlined"
);
const ReplyIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z" }),
"ReplyOutlined"
);
const FlagIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "m14 6-1-2H5v17h2v-7h5l1 2h7V6h-6zm4 8h-4l-1-2H7V6h5l1 2h5v6z" }),
"OutlinedFlagOutlined"
);
const ListAltIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M11 7h6v2h-6zm0 4h6v2h-6zm0 4h6v2h-6zM7 7h2v2H7zm0 4h2v2H7zm0 4h2v2H7zM20.1 3H3.9c-.5 0-.9.4-.9.9v16.2c0 .4.4.9.9.9h16.2c.4 0 .9-.5.9-.9V3.9c0-.5-.5-.9-.9-.9zM19 19H5V5h14v14z" }),
"ListAltOutlined"
);
const RateReviewIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17l-.59.59-.58.58V4h16v12zm-9.5-2H18v-2h-5.5zm3.86-5.87c.2-.2.2-.51 0-.71l-1.77-1.77c-.2-.2-.51-.2-.71 0L6 11.53V14h2.47l5.89-5.87z" }),
"RateReviewOutlined"
);
const BookmarkBorderIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15-5-2.18L7 18V5h10v13z" }),
"BookmarkBorderOutlined"
);
export {
BookmarkBorderIcon as B,
CommentIcon as C,
ExpandMoreIcon as E,
FlagIcon as F,
LockOpenIcon as L,
ReplyIcon as R,
ShareIcon as S,
ThumbUpIcon as T,
ThumbDownIcon as a,
ListAltIcon as b,
RateReviewIcon as c
};
//# sourceMappingURL=BookmarkBorder-2c120ae6.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
import { jsx } from "react/jsx-runtime";
import { c as createSvgIcon } from "../server-entry.mjs";
const CalendarTodayIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V10h16v11zm0-13H4V5h16v3z" }),
"CalendarTodayOutlined"
);
export {
CalendarTodayIcon as C
};
//# sourceMappingURL=CalendarToday-257ff5df.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CalendarToday-257ff5df.mjs","sources":["../../../common/resources/client/icons/material/CalendarToday.tsx"],"sourcesContent":["import {createSvgIcon} from '../create-svg-icon';\n\nexport const CalendarTodayIcon = createSvgIcon(\n <path d=\"M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V10h16v11zm0-13H4V5h16v3z\" />\n, 'CalendarTodayOutlined');\n"],"names":[],"mappings":";;AAEO,MAAM,oBAAoB;AAAA,EAC/B,oBAAC,QAAK,EAAA,GAAE,iIAAiI,CAAA;AAAA,EACzI;AAAuB;"}

View File

@@ -0,0 +1,238 @@
import { jsx, jsxs } from "react/jsx-runtime";
import React, { useRef, useCallback, cloneElement } from "react";
import { useValueEffect, useResizeObserver, useLayoutEffect } from "@react-aria/utils";
import clsx from "clsx";
import { c as createSvgIcon, i as useTrans, ah as MenuTrigger, I as IconButton, ai as Menu, h as Item } from "../server-entry.mjs";
const ChevronRightIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6-6-6z" }),
"ChevronRightOutlined"
);
function BreadcrumbItem(props) {
const {
isCurrent,
sizeStyle: sizeStyle2,
isMenuTrigger,
isClickable,
isDisabled,
onSelected,
className,
isMenuItem,
isLink
} = props;
const children = typeof props.children === "function" ? props.children({ isMenuItem }) : props.children;
if (isMenuItem) {
return children;
}
const domProps = isMenuTrigger ? {} : {
tabIndex: isLink && !isDisabled ? 0 : void 0,
role: isLink ? "link" : void 0,
"aria-disabled": isLink ? isDisabled : void 0,
"aria-current": isCurrent && isLink ? "page" : void 0,
onClick: () => onSelected == null ? void 0 : onSelected()
};
return /* @__PURE__ */ jsxs(
"li",
{
className: clsx(
`relative inline-flex min-w-0 flex-shrink-0 items-center justify-start ${sizeStyle2 == null ? void 0 : sizeStyle2.font}`,
(!isClickable || isDisabled) && "pointer-events-none",
!isCurrent && isDisabled && "text-disabled"
),
children: [
/* @__PURE__ */ jsx(
"div",
{
...domProps,
className: clsx(
className,
"cursor-pointer overflow-hidden whitespace-nowrap rounded px-8",
!isMenuTrigger && "py-4 hover:bg-hover",
!isMenuTrigger && isLink && "outline-none focus-visible:ring"
),
children
}
),
isCurrent === false && /* @__PURE__ */ jsx(
ChevronRightIcon,
{
size: sizeStyle2 == null ? void 0 : sizeStyle2.icon,
className: clsx(isDisabled ? "text-disabled" : "text-muted")
}
)
]
}
);
}
const MoreHorizIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" }),
"MoreHorizOutlined"
);
const MIN_VISIBLE_ITEMS = 1;
const MAX_VISIBLE_ITEMS = 10;
function Breadcrumb(props) {
const {
size = "md",
children,
isDisabled,
className,
currentIsClickable,
isNavigation
} = props;
const { trans } = useTrans();
const style = sizeStyle(size);
const childArray = [];
React.Children.forEach(children, (child) => {
if (React.isValidElement(child)) {
childArray.push(child);
}
});
const domRef = useRef(null);
const listRef = useRef(null);
const [visibleItems, setVisibleItems] = useValueEffect(childArray.length);
const updateOverflow = useCallback(() => {
const computeVisibleItems = (itemCount) => {
var _a;
const currListRef = listRef.current;
if (!currListRef) {
return;
}
const listItems = Array.from(currListRef.children);
if (!listItems.length)
return;
const containerWidth = currListRef.offsetWidth;
const isShowingMenu = childArray.length > itemCount;
let calculatedWidth = 0;
let newVisibleItems = 0;
let maxVisibleItems = MAX_VISIBLE_ITEMS;
calculatedWidth += listItems.shift().offsetWidth;
newVisibleItems++;
if (isShowingMenu) {
calculatedWidth += ((_a = listItems.shift()) == null ? void 0 : _a.offsetWidth) ?? 0;
maxVisibleItems--;
}
if (calculatedWidth >= containerWidth) {
newVisibleItems--;
}
if (listItems.length > 0) {
const last = listItems.pop();
last.style.overflow = "visible";
calculatedWidth += last.offsetWidth;
if (calculatedWidth < containerWidth) {
newVisibleItems++;
}
last.style.overflow = "";
}
for (const breadcrumb of listItems.reverse()) {
calculatedWidth += breadcrumb.offsetWidth;
if (calculatedWidth < containerWidth) {
newVisibleItems++;
}
}
return Math.max(
MIN_VISIBLE_ITEMS,
Math.min(maxVisibleItems, newVisibleItems)
);
};
setVisibleItems(function* () {
yield childArray.length;
const newVisibleItems = computeVisibleItems(childArray.length);
yield newVisibleItems;
if (newVisibleItems < childArray.length && newVisibleItems > 1) {
yield computeVisibleItems(newVisibleItems);
}
});
}, [listRef, children, setVisibleItems]);
useResizeObserver({ ref: domRef, onResize: updateOverflow });
useLayoutEffect(updateOverflow, [children]);
let contents = childArray;
if (childArray.length > visibleItems) {
const selectedKey = childArray.length - 1;
const menuItem = /* @__PURE__ */ jsx(BreadcrumbItem, { sizeStyle: style, isMenuTrigger: true, children: /* @__PURE__ */ jsxs(MenuTrigger, { selectionMode: "single", selectedValue: selectedKey, children: [
/* @__PURE__ */ jsx(IconButton, { "aria-label": "…", disabled: isDisabled, size: style.btn, children: /* @__PURE__ */ jsx(MoreHorizIcon, {}) }),
/* @__PURE__ */ jsx(Menu, { children: childArray.map((child, index) => {
const isLast = selectedKey === index;
return /* @__PURE__ */ jsx(
Item,
{
value: index,
onSelected: () => {
var _a, _b;
if (!isLast) {
(_b = (_a = child.props).onSelected) == null ? void 0 : _b.call(_a);
}
},
children: cloneElement(child, { isMenuItem: true })
},
index
);
}) })
] }) }, "menu");
contents = [menuItem];
const breadcrumbs = [...childArray];
let endItems = visibleItems;
if (visibleItems > 1) {
contents.unshift(breadcrumbs.shift());
endItems--;
}
contents.push(...breadcrumbs.slice(-endItems));
}
const lastIndex = contents.length - 1;
const breadcrumbItems = contents.map((child, index) => {
const isCurrent = index === lastIndex;
const isClickable = !isCurrent || currentIsClickable;
return cloneElement(child, {
key: child.key || index,
isCurrent,
sizeStyle: style,
isClickable,
isDisabled,
isLink: isNavigation && child.key !== "menu"
});
});
const Element = isNavigation ? "nav" : "div";
return /* @__PURE__ */ jsx(
Element,
{
className: clsx(className, "w-full min-w-0"),
"aria-label": trans({ message: "Breadcrumbs" }),
ref: domRef,
children: /* @__PURE__ */ jsx(
"ol",
{
ref: listRef,
className: clsx("flex flex-nowrap justify-start", style.minHeight),
children: breadcrumbItems
}
)
}
);
}
function sizeStyle(size) {
switch (size) {
case "sm":
return { font: "text-sm", icon: "sm", btn: "sm", minHeight: "min-h-36" };
case "lg":
return { font: "text-lg", icon: "md", btn: "md", minHeight: "min-h-42" };
case "xl":
return { font: "text-xl", icon: "md", btn: "md", minHeight: "min-h-42" };
default:
return { font: "text-base", icon: "md", btn: "md", minHeight: "min-h-42" };
}
}
const EditIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "m14.06 9.02.92.92L5.92 19H5v-.92l9.06-9.06M17.66 3c-.25 0-.51.1-.7.29l-1.83 1.83 3.75 3.75 1.83-1.83c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.2-.2-.45-.29-.71-.29zm-3.6 3.19L3 17.25V21h3.75L17.81 9.94l-3.75-3.75z" }),
"EditOutlined"
);
const OpenInNewIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" }),
"OpenInNewOutlined"
);
export {
Breadcrumb as B,
ChevronRightIcon as C,
EditIcon as E,
MoreHorizIcon as M,
OpenInNewIcon as O,
BreadcrumbItem as a
};
//# sourceMappingURL=OpenInNew-3b47a656.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
import { jsx } from "react/jsx-runtime";
import { c as createSvgIcon } from "../server-entry.mjs";
const TaskAltIcon = createSvgIcon(
/* @__PURE__ */ jsx("path", { d: "M22 5.18 10.59 16.6l-4.24-4.24 1.41-1.41 2.83 2.83 10-10L22 5.18zm-2.21 5.04c.13.57.21 1.17.21 1.78 0 4.42-3.58 8-8 8s-8-3.58-8-8 3.58-8 8-8c1.58 0 3.04.46 4.28 1.25l1.44-1.44C16.1 2.67 14.13 2 12 2 6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-1.19-.22-2.33-.6-3.39l-1.61 1.61z" }),
"TaskAltOutlined"
);
export {
TaskAltIcon as T
};
//# sourceMappingURL=TaskAlt-798b1c02.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"TaskAlt-798b1c02.mjs","sources":["../../../common/resources/client/icons/material/TaskAlt.tsx"],"sourcesContent":["import {createSvgIcon} from '../create-svg-icon';\n\nexport const TaskAltIcon = createSvgIcon(\n <path d=\"M22 5.18 10.59 16.6l-4.24-4.24 1.41-1.41 2.83 2.83 10-10L22 5.18zm-2.21 5.04c.13.57.21 1.17.21 1.78 0 4.42-3.58 8-8 8s-8-3.58-8-8 3.58-8 8-8c1.58 0 3.04.46 4.28 1.25l1.44-1.44C16.1 2.67 14.13 2 12 2 6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-1.19-.22-2.33-.6-3.39l-1.61 1.61z\" />\n, 'TaskAltOutlined');\n"],"names":[],"mappings":";;AAEO,MAAM,cAAc;AAAA,EACzB,oBAAC,QAAK,EAAA,GAAE,4RAA4R,CAAA;AAAA,EACpS;AAAiB;"}

View File

@@ -0,0 +1,97 @@
import { jsx } from "react/jsx-runtime";
import ace from "ace-builds/src-noconflict/ace.js";
import { useRef, useEffect } from "react";
import AceEditorRender from "react-ace";
import "ace-builds/src-noconflict/mode-css.js";
import "ace-builds/src-noconflict/mode-html.js";
import "ace-builds/src-noconflict/mode-javascript.js";
import "ace-builds/src-noconflict/mode-php_laravel_blade.js";
import "ace-builds/src-noconflict/theme-chrome.js";
import "ace-builds/src-noconflict/theme-tomorrow_night.js";
import "ace-builds/src-noconflict/ext-language_tools.js";
import Beautify from "ace-builds/src-noconflict/ext-beautify.js";
import { bc as useIsDarkMode } from "../server-entry.mjs";
import "react-dom/server";
import "process";
import "http";
import "@tanstack/react-query";
import "axios";
import "react-router-dom/server.mjs";
import "framer-motion";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "react-router-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
const cssWorkerUrl = "/assets/worker-css-b70c72a0.js";
const htmlWorkerUrl = "/assets/worker-html-63aac2ef.js";
const phpWorkerUrl = "/assets/worker-php-47e5dfe7.js";
const javascriptWorkerUrl = "/assets/worker-javascript-c4599136.js";
ace.config.setModuleUrl("ace/mode/css_worker", cssWorkerUrl);
ace.config.setModuleUrl("ace/mode/html_worker", htmlWorkerUrl);
ace.config.setModuleUrl("ace/mode/php_worker", phpWorkerUrl);
ace.config.setModuleUrl("ace/mode/javascript_worker", javascriptWorkerUrl);
function AceEditor({
mode,
onChange,
onIsValidChange,
defaultValue,
beautify = true,
editorRef: propsEditorRef
}) {
const isDarkMode = useIsDarkMode();
const defaultRef = useRef(null);
const editorRef = propsEditorRef || defaultRef;
useEffect(() => {
if (beautify && editorRef.current) {
Beautify.beautify(editorRef.current.editor.session);
}
}, [beautify, editorRef]);
return /* @__PURE__ */ jsx(
AceEditorRender,
{
ref: editorRef,
width: "auto",
height: "auto",
wrapEnabled: true,
className: "absolute inset-0",
focus: true,
mode,
theme: isDarkMode ? "tomorrow_night" : "chrome",
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
defaultValue,
onChange,
editorProps: { $blockScrolling: true },
commands: Beautify.commands,
onValidate: (annotations) => {
const isValid = annotations.filter((a) => a.type === "error").length === 0;
onIsValidChange(isValid);
}
}
);
}
export {
AceEditor as default
};
//# sourceMappingURL=ace-editor-481d400c.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ace-editor-481d400c.mjs","sources":["../../../node_modules/ace-builds/src-noconflict/worker-css.js?url","../../../node_modules/ace-builds/src-noconflict/worker-html.js?url","../../../node_modules/ace-builds/src-noconflict/worker-php.js?url","../../../node_modules/ace-builds/src-noconflict/worker-javascript.js?url","../../../common/resources/client/ace-editor/ace-editor.tsx"],"sourcesContent":["export default \"__VITE_ASSET__aff451cf__\"","export default \"__VITE_ASSET__bea50456__\"","export default \"__VITE_ASSET__a530ae0a__\"","export default \"__VITE_ASSET__91a578e2__\"","import ace from 'ace-builds/src-noconflict/ace';\nimport cssWorkerUrl from 'ace-builds/src-noconflict/worker-css?url';\nimport htmlWorkerUrl from 'ace-builds/src-noconflict/worker-html?url';\nimport phpWorkerUrl from 'ace-builds/src-noconflict/worker-php?url';\nimport javascriptWorkerUrl from 'ace-builds/src-noconflict/worker-javascript?url';\nimport React, {MutableRefObject, useEffect, useRef} from 'react';\nimport AceEditorRender from 'react-ace';\nimport ReactAce from 'react-ace';\nimport 'ace-builds/src-noconflict/mode-css';\nimport 'ace-builds/src-noconflict/mode-html';\nimport 'ace-builds/src-noconflict/mode-javascript';\nimport 'ace-builds/src-noconflict/mode-php_laravel_blade';\nimport 'ace-builds/src-noconflict/theme-chrome';\nimport 'ace-builds/src-noconflict/theme-tomorrow_night';\nimport 'ace-builds/src-noconflict/ext-language_tools';\nimport Beautify from 'ace-builds/src-noconflict/ext-beautify';\nimport {useIsDarkMode} from '../ui/themes/use-is-dark-mode';\n\nace.config.setModuleUrl('ace/mode/css_worker', cssWorkerUrl);\nace.config.setModuleUrl('ace/mode/html_worker', htmlWorkerUrl);\nace.config.setModuleUrl('ace/mode/php_worker', phpWorkerUrl);\nace.config.setModuleUrl('ace/mode/javascript_worker', javascriptWorkerUrl);\n\ninterface Props {\n mode: 'css' | 'html' | 'javascript' | 'php_laravel_blade';\n onChange: (value: string) => void;\n onIsValidChange: (isValid: boolean) => void;\n defaultValue: string;\n beautify?: boolean;\n editorRef?: MutableRefObject<ReactAce | null>;\n}\nexport default function AceEditor({\n mode,\n onChange,\n onIsValidChange,\n defaultValue,\n beautify = true,\n editorRef: propsEditorRef,\n}: Props) {\n const isDarkMode = useIsDarkMode();\n const defaultRef = useRef<ReactAce | null>(null);\n const editorRef = propsEditorRef || defaultRef;\n\n useEffect(() => {\n if (beautify && editorRef.current) {\n Beautify.beautify(editorRef.current.editor.session);\n }\n }, [beautify, editorRef]);\n\n return (\n <AceEditorRender\n ref={editorRef}\n width=\"auto\"\n height=\"auto\"\n wrapEnabled\n className=\"absolute inset-0\"\n focus\n mode={mode}\n theme={isDarkMode ? 'tomorrow_night' : 'chrome'}\n enableBasicAutocompletion\n enableLiveAutocompletion\n defaultValue={defaultValue}\n onChange={onChange}\n editorProps={{$blockScrolling: true}}\n commands={Beautify.commands}\n onValidate={annotations => {\n const isValid =\n annotations.filter(a => a.type === 'error').length === 0;\n onIsValidChange(isValid);\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAe,eAAA;ACAf,MAAe,gBAAA;ACAf,MAAe,eAAA;ACAf,MAAe,sBAAA;ACkBf,IAAI,OAAO,aAAa,uBAAuB,YAAY;AAC3D,IAAI,OAAO,aAAa,wBAAwB,aAAa;AAC7D,IAAI,OAAO,aAAa,uBAAuB,YAAY;AAC3D,IAAI,OAAO,aAAa,8BAA8B,mBAAmB;AAUzE,SAAwB,UAAU;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,WAAW;AACb,GAAU;AACR,QAAM,aAAa;AACb,QAAA,aAAa,OAAwB,IAAI;AAC/C,QAAM,YAAY,kBAAkB;AAEpC,YAAU,MAAM;AACV,QAAA,YAAY,UAAU,SAAS;AACjC,eAAS,SAAS,UAAU,QAAQ,OAAO,OAAO;AAAA,IACpD;AAAA,EAAA,GACC,CAAC,UAAU,SAAS,CAAC;AAGtB,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,OAAM;AAAA,MACN,QAAO;AAAA,MACP,aAAW;AAAA,MACX,WAAU;AAAA,MACV,OAAK;AAAA,MACL;AAAA,MACA,OAAO,aAAa,mBAAmB;AAAA,MACvC,2BAAyB;AAAA,MACzB,0BAAwB;AAAA,MACxB;AAAA,MACA;AAAA,MACA,aAAa,EAAC,iBAAiB,KAAI;AAAA,MACnC,UAAU,SAAS;AAAA,MACnB,YAAY,CAAe,gBAAA;AACnB,cAAA,UACJ,YAAY,OAAO,CAAA,MAAK,EAAE,SAAS,OAAO,EAAE,WAAW;AACzD,wBAAgB,OAAO;AAAA,MACzB;AAAA,IAAA;AAAA,EAAA;AAGN;","x_google_ignoreList":[0,1,2,3]}

View File

@@ -0,0 +1,73 @@
import { jsxs, jsx } from "react/jsx-runtime";
import { useState } from "react";
import { u as useAdminReport, R as ReportDateSelector, A as AdminHeaderReport, V as VisitorsReportCharts } from "./admin-routes-06d8abf9.mjs";
import { l as StaticPageTitle, T as Trans } from "../server-entry.mjs";
import { D as DateRangePresets } from "./user-profile-link-0bca566c.mjs";
import "react-router-dom";
import "clsx";
import "framer-motion";
import "@react-stately/utils";
import "@tanstack/react-query";
import "./section-helper-708a2a0a.mjs";
import "./OpenInNew-3b47a656.mjs";
import "@react-aria/utils";
import "react-hook-form";
import "@internationalized/date";
import "zustand";
import "zustand/middleware";
import "zustand/middleware/immer";
import "deepmerge";
import "react-colorful";
import "@react-stately/color";
import "immer";
import "nanoid";
import "deep-object-diff";
import "dot-object";
import "@react-aria/focus";
import "nano-memoize";
import "@tanstack/react-virtual";
import "react-dom/server";
import "process";
import "http";
import "axios";
import "react-router-dom/server.mjs";
import "slugify";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "@internationalized/number";
import "@react-aria/ssr";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
import "fscreen";
import "zustand/traditional";
import "@react-aria/interactions";
function AdminReportPage() {
const [dateRange, setDateRange] = useState(() => {
return DateRangePresets[2].getRangeValue();
});
const { isLoading, data } = useAdminReport({ dateRange });
const title = /* @__PURE__ */ jsx(Trans, { message: "Visitors report" });
return /* @__PURE__ */ jsxs("div", { className: "min-h-full gap-12 overflow-x-hidden p-12 md:gap-18 md:p-18", children: [
/* @__PURE__ */ jsxs("div", { className: "mb-24 items-center justify-between gap-24 md:flex", children: [
/* @__PURE__ */ jsx(StaticPageTitle, { children: title }),
/* @__PURE__ */ jsx("h1", { className: "mb-24 text-3xl font-light md:mb-0", children: title }),
/* @__PURE__ */ jsx(ReportDateSelector, { value: dateRange, onChange: setDateRange })
] }),
/* @__PURE__ */ jsx(AdminHeaderReport, { report: data == null ? void 0 : data.headerReport }),
/* @__PURE__ */ jsx(
VisitorsReportCharts,
{
report: data == null ? void 0 : data.visitorsReport,
isLoading
}
)
] });
}
export {
AdminReportPage as default
};
//# sourceMappingURL=admin-report-page-181c7a5d.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"admin-report-page-181c7a5d.mjs","sources":["../../../common/resources/client/admin/analytics/admin-report-page.tsx"],"sourcesContent":["import React, {useState} from 'react';\nimport {useAdminReport} from './use-admin-report';\nimport {Trans} from '../../i18n/trans';\nimport {StaticPageTitle} from '../../seo/static-page-title';\nimport {AdminHeaderReport} from '@common/admin/analytics/admin-header-report';\nimport {VisitorsReportCharts} from '@common/admin/analytics/visitors-report-charts';\nimport {DateRangeValue} from '@common/ui/forms/input-field/date/date-range-picker/date-range-value';\nimport {DateRangePresets} from '@common/ui/forms/input-field/date/date-range-picker/dialog/date-range-presets';\nimport {ReportDateSelector} from '@common/admin/analytics/report-date-selector';\n\nexport default function AdminReportPage() {\n const [dateRange, setDateRange] = useState<DateRangeValue>(() => {\n // This week\n return DateRangePresets[2].getRangeValue();\n });\n const {isLoading, data} = useAdminReport({dateRange});\n const title = <Trans message=\"Visitors report\" />;\n\n return (\n <div className=\"min-h-full gap-12 overflow-x-hidden p-12 md:gap-18 md:p-18\">\n <div className=\"mb-24 items-center justify-between gap-24 md:flex\">\n <StaticPageTitle>{title}</StaticPageTitle>\n <h1 className=\"mb-24 text-3xl font-light md:mb-0\">{title}</h1>\n <ReportDateSelector value={dateRange} onChange={setDateRange} />\n </div>\n <AdminHeaderReport report={data?.headerReport} />\n <VisitorsReportCharts\n report={data?.visitorsReport}\n isLoading={isLoading}\n />\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,SAAwB,kBAAkB;AACxC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAyB,MAAM;AAExD,WAAA,iBAAiB,CAAC,EAAE;EAAc,CAC1C;AACD,QAAM,EAAC,WAAW,KAAA,IAAQ,eAAe,EAAC,WAAU;AACpD,QAAM,QAAQ,oBAAC,OAAM,EAAA,SAAQ,kBAAkB,CAAA;AAG7C,SAAA,qBAAC,OAAI,EAAA,WAAU,8DACb,UAAA;AAAA,IAAC,qBAAA,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,MAAA,oBAAC,mBAAiB,UAAM,MAAA,CAAA;AAAA,MACvB,oBAAA,MAAA,EAAG,WAAU,qCAAqC,UAAM,OAAA;AAAA,MACxD,oBAAA,oBAAA,EAAmB,OAAO,WAAW,UAAU,cAAc;AAAA,IAAA,GAChE;AAAA,IACC,oBAAA,mBAAA,EAAkB,QAAQ,6BAAM,aAAc,CAAA;AAAA,IAC/C;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,QAAQ,6BAAM;AAAA,QACd;AAAA,MAAA;AAAA,IACF;AAAA,EACF,EAAA,CAAA;AAEJ;"}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,383 @@
import { jsx } from "react/jsx-runtime";
import { Node, mergeAttributes, useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { Underline } from "@tiptap/extension-underline";
import { Link } from "@tiptap/extension-link";
import Image from "@tiptap/extension-image";
import { useRef, useEffect } from "react";
import { Superscript } from "@tiptap/extension-superscript";
import { Subscript } from "@tiptap/extension-subscript";
import { Color } from "@tiptap/extension-color";
import { TextStyle } from "@tiptap/extension-text-style";
import { TextAlign } from "@tiptap/extension-text-align";
import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
import { Extension } from "@tiptap/core";
import { TextSelection, AllSelection } from "prosemirror-state";
import { createLowlight } from "lowlight";
import javascript from "highlight.js/lib/languages/javascript";
import typescript from "highlight.js/lib/languages/typescript";
import html from "highlight.js/lib/languages/xml";
import css from "highlight.js/lib/languages/css";
import php from "highlight.js/lib/languages/php";
import shell from "highlight.js/lib/languages/shell";
import bash from "highlight.js/lib/languages/bash";
import ruby from "highlight.js/lib/languages/ruby";
import python from "highlight.js/lib/languages/python";
import java from "highlight.js/lib/languages/java";
import c from "highlight.js/lib/languages/c";
import { bt as useCallbackRef } from "../server-entry.mjs";
import "react-dom/server";
import "process";
import "http";
import "@tanstack/react-query";
import "axios";
import "react-router-dom/server.mjs";
import "framer-motion";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "react-router-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
const BackgroundColor = Extension.create({
name: "backgroundColor",
addOptions() {
return {
types: ["textStyle"]
};
},
addGlobalAttributes() {
return [
{
types: this.options.types,
attributes: {
backgroundColor: {
default: null,
parseHTML: (element) => element.style.backgroundColor.replace(/['"]+/g, ""),
renderHTML: (attributes) => {
if (!attributes.backgroundColor) {
return {};
}
return {
style: `background-color: ${attributes.backgroundColor}`
};
}
}
}
}
];
},
addCommands() {
return {
setBackgroundColor: (backgroundColor) => ({ chain }) => {
return chain().setMark("textStyle", { backgroundColor }).run();
},
unsetBackgroundColor: () => ({ chain }) => {
return chain().setMark("textStyle", { backgroundColor: null }).removeEmptyTextStyle().run();
}
};
}
});
const Indent = Extension.create({
name: "indent",
addOptions: () => {
return {
types: ["listItem", "paragraph"],
minLevel: 0,
maxLevel: 6
};
},
addGlobalAttributes() {
return [
{
types: this.options.types,
attributes: {
indent: {
renderHTML: (attributes) => {
return (attributes == null ? void 0 : attributes.indent) > this.options.minLevel ? { "data-indent": attributes.indent } : null;
},
parseHTML: (element) => {
const level = Number(element.getAttribute("data-indent"));
return level && level > this.options.minLevel ? level : null;
}
}
}
}
];
},
addCommands() {
const setNodeIndentMarkup = (tr, pos, delta) => {
var _a;
const node = (_a = tr == null ? void 0 : tr.doc) == null ? void 0 : _a.nodeAt(pos);
if (node) {
const nextLevel = (node.attrs.indent || 0) + delta;
const { minLevel, maxLevel } = this.options;
const indent = (
// eslint-disable-next-line no-nested-ternary
nextLevel < minLevel ? minLevel : nextLevel > maxLevel ? maxLevel : nextLevel
);
if (indent !== node.attrs.indent) {
const { indent: oldIndent, ...currentAttrs } = node.attrs;
const nodeAttrs = indent > minLevel ? { ...currentAttrs, indent } : currentAttrs;
return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks);
}
}
return tr;
};
const updateIndentLevel = (tr, delta) => {
const { doc, selection } = tr;
if (doc && selection && (selection instanceof TextSelection || selection instanceof AllSelection)) {
const { from, to } = selection;
doc.nodesBetween(from, to, (node, pos) => {
if (this.options.types.includes(node.type.name)) {
tr = setNodeIndentMarkup(tr, pos, delta);
return false;
}
return true;
});
}
return tr;
};
const applyIndent = (direction) => () => ({ tr, state, dispatch }) => {
const { selection } = state;
tr = tr.setSelection(selection);
tr = updateIndentLevel(tr, direction);
if (tr.docChanged) {
dispatch == null ? void 0 : dispatch(tr);
return true;
}
return false;
};
return {
indent: applyIndent(1),
outdent: applyIndent(-1)
};
},
addKeyboardShortcuts() {
return {
Tab: ({ editor }) => {
if (editor.state.selection.to > editor.state.selection.from) {
return this.editor.commands.indent();
}
return false;
},
"Shift-Tab": ({ editor }) => {
if (editor.state.selection.to > editor.state.selection.from) {
return this.editor.commands.outdent();
}
return false;
}
};
}
});
const Embed = Node.create({
name: "embed",
group: "block",
atom: true,
addAttributes() {
return {
allowfullscreen: {
default: null
},
allow: {
default: "autoplay; fullscreen; picture-in-picture"
},
src: {
default: null
}
};
},
parseHTML() {
return [
{
tag: "iframe"
}
];
},
renderHTML({ HTMLAttributes }) {
return [
"iframe",
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
];
},
addCommands() {
return {
setEmbed: (options) => ({ commands }) => {
return commands.insertContent({
type: this.name,
attrs: options
});
}
};
}
});
const highlightMaterialPalenight = "";
const lowlight = createLowlight();
lowlight.register("javascript", javascript);
lowlight.register("typescript", typescript);
lowlight.register("html", html);
lowlight.register("css", css);
lowlight.register("php", php);
lowlight.register("shell", shell);
lowlight.register("bash", bash);
lowlight.register("ruby", ruby);
lowlight.register("python", python);
lowlight.register("java", java);
lowlight.register("c", c);
const InfoBlock = Node.create({
name: "be-info-block",
group: "block",
content: "inline*",
defining: true,
addOptions() {
return {
types: ["important", "warning", "success"],
defaultType: "success"
};
},
addAttributes() {
return {
type: {
default: this.options.defaultType,
parseHTML: (element) => {
for (const type of this.options.types) {
if (element.classList.contains(type)) {
return type;
}
}
return this.options.defaultType;
},
renderHTML: (attrs) => {
return { class: attrs.type };
}
}
};
},
parseHTML() {
return [
{
tag: "div",
contentElement: "p",
getAttrs: (node) => node.classList.contains("info-block") && null
}
];
},
renderHTML({ HTMLAttributes }) {
return [
"div",
mergeAttributes(HTMLAttributes, {
class: "info-block"
}),
["div", { class: "title" }, "Important:"],
["p", 0]
];
},
addCommands() {
return {
addInfo: (attributes) => ({ commands }) => {
return commands.setNode(this.name, attributes);
}
};
}
});
function ArticleBodyEditor({
initialContent = "",
children,
onLoad: _onLoad,
onCtrlEnter,
minHeight = "min-h-320",
autoFocus
}) {
const onLoad = useCallbackRef(_onLoad);
const calledOnLoad = useRef(false);
const extensions = [
StarterKit.configure({
codeBlock: false
}),
Underline,
Link.extend({
inclusive: false,
validate: {
// only linkify links that start with a protocol
url: (value) => /^https?:\/\//.test(value)
}
}),
Image,
Superscript,
Subscript,
TextStyle,
Color,
BackgroundColor,
Indent,
CodeBlockLowlight.configure({
lowlight
}),
TextAlign.configure({
types: ["heading", "paragraph"]
}),
InfoBlock,
Embed
];
if (onCtrlEnter) {
extensions.push(
Extension.create({
addKeyboardShortcuts: () => ({
"Cmd-Enter"() {
onCtrlEnter();
return true;
},
"Ctrl-Enter"() {
onCtrlEnter();
return true;
}
})
})
);
}
const editor = useEditor({
extensions,
onFocus: () => {
},
autofocus: autoFocus,
content: initialContent
});
useEffect(() => {
if (editor) {
return () => editor.destroy();
}
}, [editor]);
if (!editor) {
return null;
}
if (editor && onLoad && !calledOnLoad.current) {
onLoad(editor);
calledOnLoad.current = true;
}
return children(
/* @__PURE__ */ jsx(EditorContent, { className: minHeight, editor }),
editor
);
}
export {
ArticleBodyEditor as default
};
//# sourceMappingURL=article-body-editor-9e195fab.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,831 @@
import { jsx, jsxs } from "react/jsx-runtime";
import { Navigate, Outlet, Link, useSearchParams, useParams, Routes, Route } from "react-router-dom";
import { b6 as useAuth, as as useUser, l as StaticPageTitle, T as Trans, N as Navbar, a9 as ProgressCircle, b1 as Footer, aa as useNavigate, u as useSettings, B as Button, q as queryClient, m as message, b as apiClient, aA as useProducts, bo as BillingCycleRadio, bp as findBestPrice, o as opacityAnimation, aB as FormattedPrice, M as CheckIcon, a2 as Skeleton, i as useTrans, t as toast, n as showHttpErrorToast, R as FormattedDate, Q as Chip, x as SvgImage, b8 as FormattedCurrency } from "../server-entry.mjs";
import { Fragment, useState, useRef, useEffect, createElement } from "react";
import { B as Breadcrumb, a as BreadcrumbItem, E as EditIcon, O as OpenInNewIcon } from "./OpenInNew-3b47a656.mjs";
import { S as StripeElementsForm, B as BillingRedirectMessage } from "./billing-redirect-message-d4e5c39f.mjs";
import { loadStripe } from "@stripe/stripe-js";
import { AnimatePresence, m } from "framer-motion";
import { useMutation, useQuery } from "@tanstack/react-query";
import { u as useCancelSubscription, a as useResumeSubscription, S as SectionHelper } from "./section-helper-708a2a0a.mjs";
import { C as CalendarTodayIcon } from "./CalendarToday-257ff5df.mjs";
import "react-dom/server";
import "process";
import "http";
import "axios";
import "react-router-dom/server.mjs";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
import "./TaskAlt-798b1c02.mjs";
function SubscribedRoute({ children }) {
const { isSubscribed } = useAuth();
if (!isSubscribed) {
return /* @__PURE__ */ jsx(Navigate, { to: "/pricing", replace: true });
}
return children || /* @__PURE__ */ jsx(Outlet, {});
}
function BillingPageLayout() {
const { user } = useAuth();
const query = useUser(user.id, {
with: ["subscriptions.product", "subscriptions.price"]
});
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(StaticPageTitle, { children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(Navbar, { menuPosition: "billing-page" }),
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsx("div", { className: "container mx-auto my-24 px-24 flex-auto", children: query.isLoading ? /* @__PURE__ */ jsx(
ProgressCircle,
{
className: "my-80",
"aria-label": "Loading user..",
isIndeterminate: true
}
) : /* @__PURE__ */ jsx(Outlet, {}) }),
/* @__PURE__ */ jsx(Footer, { className: "container mx-auto px-24" })
] })
] });
}
const previousUrl$5 = "/billing";
function ChangePaymentMethodLayout() {
const navigate = useNavigate();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl$5), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Payment method" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Change payment method" }) }),
/* @__PURE__ */ jsx(Outlet, {})
] });
}
const previousUrl$4 = "/billing";
function ChangePaymentMethodPage() {
const { base_url } = useSettings();
return /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx(
StripeElementsForm,
{
type: "setupIntent",
submitLabel: /* @__PURE__ */ jsx(Trans, { message: "Change" }),
returnUrl: `${base_url}/billing/change-payment-method/done`
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full mt-16",
size: "md",
to: previousUrl$4,
elementType: Link,
type: "button",
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
)
] });
}
function useBillingUser() {
var _a, _b, _c;
const query = useUser("me", {
with: ["subscriptions.product", "subscriptions.price"]
});
const subscription = (_b = (_a = query.data) == null ? void 0 : _a.user.subscriptions) == null ? void 0 : _b[0];
return { subscription, isLoading: query.isLoading, user: (_c = query.data) == null ? void 0 : _c.user };
}
function invalidateBillingUserQuery() {
queryClient.invalidateQueries({ queryKey: ["users"] });
}
const previousUrl$3 = "/billing";
function ChangePaymentMethodDone() {
const {
billing: { stripe_public_key }
} = useSettings();
const navigate = useNavigate();
const [params] = useSearchParams();
const clientSecret = params.get("setup_intent_client_secret");
const [messageConfig, setMessageConfig] = useState();
const stripeInitiated = useRef();
useEffect(() => {
if (stripeInitiated.current || !clientSecret)
return;
loadStripe(stripe_public_key).then((stripe) => {
if (!stripe) {
setMessageConfig(getRedirectMessageConfig());
return;
}
stripe.retrieveSetupIntent(clientSecret).then(({ setupIntent }) => {
if ((setupIntent == null ? void 0 : setupIntent.status) === "succeeded") {
changeDefaultPaymentMethod(setupIntent.payment_method).then(
() => {
invalidateBillingUserQuery();
}
);
}
setMessageConfig(getRedirectMessageConfig(setupIntent == null ? void 0 : setupIntent.status));
});
});
stripeInitiated.current = true;
}, [stripe_public_key, clientSecret]);
if (!clientSecret) {
navigate(previousUrl$3);
return null;
}
return /* @__PURE__ */ jsx(BillingRedirectMessage, { config: messageConfig });
}
function getRedirectMessageConfig(status) {
switch (status) {
case "succeeded":
return {
...redirectMessageDefaults,
message: message("Payment method changed successfully!"),
status: "success"
};
case "processing":
return {
...redirectMessageDefaults,
message: message(
"Your request is processing. We'll update you when your payment method is confirmed."
),
status: "success"
};
case "requires_payment_method":
return {
...redirectMessageDefaults,
message: message(
"Payment method confirmation failed. Please try another payment method."
),
status: "error"
};
default:
return {
...redirectMessageDefaults,
message: message("Something went wrong"),
status: "error"
};
}
}
const redirectMessageDefaults = {
link: previousUrl$3,
buttonLabel: message("Go back")
};
function changeDefaultPaymentMethod(paymentMethodId) {
return apiClient.post("billing/stripe/change-default-payment-method", {
payment_method_id: paymentMethodId
});
}
function BillingPlanPanel({ title, children }) {
return /* @__PURE__ */ jsxs("div", { className: "mb-64", children: [
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium uppercase pb-16 mb-16 border-b", children: title }),
children
] });
}
function ChangePlanPage() {
const navigate = useNavigate();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate("/billing"), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Plans" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "my-32 text-3xl font-bold md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Change your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Available plans" }), children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: /* @__PURE__ */ jsx(PlanList, {}) }) })
] });
}
function PlanList() {
var _a, _b;
const query = useProducts();
const [selectedCycle, setSelectedCycle] = useState("monthly");
if (query.isLoading) {
return /* @__PURE__ */ jsx(PlanSkeleton, {}, "plan-skeleton");
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
BillingCycleRadio,
{
products: (_a = query.data) == null ? void 0 : _a.products,
selectedCycle,
onChange: setSelectedCycle,
className: "mb-20",
size: "md"
}
),
(_b = query.data) == null ? void 0 : _b.products.map((plan) => {
const price = findBestPrice(selectedCycle, plan.prices);
if (!price || plan.hidden)
return null;
return /* @__PURE__ */ createElement(
m.div,
{
...opacityAnimation,
key: plan.id,
className: "justify-between gap-40 border-b py-32 md:flex"
},
/* @__PURE__ */ jsxs("div", { className: "mb-40 md:mb-0", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: plan.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "mt-12 text-base", children: plan.description }),
/* @__PURE__ */ jsx(FeatureList, { plan })
] }),
/* @__PURE__ */ jsx(ContinueButton, { product: plan, price })
);
})
] }, "plan-list");
}
function FeatureList({ plan }) {
if (!plan.feature_list.length)
return null;
return /* @__PURE__ */ jsxs("div", { className: "mt-32", children: [
/* @__PURE__ */ jsx("div", { className: "mb-10 text-sm font-semibold", children: /* @__PURE__ */ jsx(Trans, { message: "What's included" }) }),
plan.feature_list.map((feature) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-10 text-sm", children: [
/* @__PURE__ */ jsx(CheckIcon, { className: "text-positive", size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: feature })
] }, feature))
] });
}
function ContinueButton({ product, price }) {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
if (subscription.product_id === product.id && subscription.price_id === price.id) {
return /* @__PURE__ */ jsxs("div", { className: "flex w-[168px] items-center justify-center gap-10 text-muted", children: [
/* @__PURE__ */ jsx(CheckIcon, { size: "md" }),
/* @__PURE__ */ jsx(Trans, { message: "Current plan" })
] });
}
return /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
className: "w-[168px]",
size: "md",
elementType: Link,
to: `/billing/change-plan/${product.id}/${price.id}/confirm`,
children: /* @__PURE__ */ jsx(Trans, { message: "Continue" })
}
);
}
function PlanSkeleton() {
return /* @__PURE__ */ jsxs(
m.div,
{
...opacityAnimation,
className: "border-b py-32 text-2xl",
children: [
/* @__PURE__ */ jsx(Skeleton, { className: "mb-8" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-24" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-12" })
]
},
"plan-skeleton"
);
}
function useChangeSubscriptionPlan() {
const { trans } = useTrans();
const navigate = useNavigate();
return useMutation({
mutationFn: (props) => changePlan(props),
onSuccess: () => {
toast(trans(message("Plan changed.")));
invalidateBillingUserQuery();
navigate("/billing");
},
onError: (err) => showHttpErrorToast(err)
});
}
function changePlan({ subscriptionId, ...other }) {
return apiClient.post(`billing/subscriptions/${subscriptionId}/change-plan`, other).then((r) => r.data);
}
const previousUrl$2 = "/billing/change-plan";
function ConfirmPlanChangePage() {
const { productId, priceId } = useParams();
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const changePlan2 = useChangeSubscriptionPlan();
if (!query.data || (subscription == null ? void 0 : subscription.price_id) == priceId) {
return /* @__PURE__ */ jsx(Navigate, { to: "/billing/change-plan", replace: true });
}
const newProduct = query.data.products.find((p) => `${p.id}` === productId);
const newPrice = newProduct == null ? void 0 : newProduct.prices.find((p) => `${p.id}` === priceId);
if (!newProduct || !newPrice || !subscription) {
navigate(previousUrl$2);
return null;
}
const newDate = /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
/* @__PURE__ */ jsx(FormattedDate, { date: subscription.renews_at, preset: "long" }),
";"
] });
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate("/billing"), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { onSelected: () => navigate(previousUrl$2), children: /* @__PURE__ */ jsx(Trans, { message: "Plans" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Confirm" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Confirm your new plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Changing to" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: newProduct.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price: newPrice, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: /* @__PURE__ */ jsx(
Trans,
{
message: "You will be charged the new price starting :date",
values: { date: newDate }
}
) }),
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: () => {
changePlan2.mutate({
subscriptionId: subscription.id,
newProductId: newProduct.id,
newPriceId: newPrice.id
});
},
disabled: changePlan2.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Confirm" })
}
) }),
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl$2,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
) }),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By confirming your new plan, you agree to our terms of Service and privacy policy." }) })
] })
] }) })
] });
}
const previousUrl$1 = "/billing";
function ConfirmPlanCancellationPage() {
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const cancelSubscription = useCancelSubscription();
const product = subscription == null ? void 0 : subscription.product;
const price = subscription == null ? void 0 : subscription.price;
if (!query.data) {
return null;
}
if (!subscription || !product || !price) {
navigate(previousUrl$1);
return null;
}
const renewDate = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: /* @__PURE__ */ jsx(FormattedDate, { date: subscription.renews_at, preset: "long" }) });
const handleSubscriptionCancel = () => {
cancelSubscription.mutate(
{
subscriptionId: subscription.id
},
{
onSuccess: () => {
invalidateBillingUserQuery();
navigate("/billing");
}
}
);
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl$1), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Cancel" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Cancel your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsxs("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: [
/* @__PURE__ */ jsx(
Trans,
{
message: "Your plan will be canceled, but is still available until the end of your billing period on :date",
values: { date: renewDate }
}
),
/* @__PURE__ */ jsx("div", { className: "mt-20", children: /* @__PURE__ */ jsx(Trans, { message: "If you change your mind, you can renew your subscription." }) })
] }),
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: handleSubscriptionCancel,
disabled: cancelSubscription.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Cancel plan" })
}
) }),
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl$1,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
) }),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By cancelling your plan, you agree to our terms of service and privacy policy." }) })
] })
] }) })
] });
}
const previousUrl = "/billing";
function ConfirmPlanRenewalPage() {
const navigate = useNavigate();
const query = useProducts();
const { subscription } = useBillingUser();
const resumeSubscription = useResumeSubscription();
const product = subscription == null ? void 0 : subscription.product;
const price = subscription == null ? void 0 : subscription.price;
if (!query.data) {
return null;
}
if (!subscription || !product || !price) {
navigate(previousUrl);
return null;
}
const endDate = /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
/* @__PURE__ */ jsx(FormattedDate, { date: subscription.ends_at, preset: "long" }),
";"
] });
const handleResumeSubscription = () => {
resumeSubscription.mutate(
{
subscriptionId: subscription.id
},
{
onSuccess: () => {
invalidateBillingUserQuery();
navigate("/billing");
}
}
);
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(Breadcrumb, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { isLink: true, onSelected: () => navigate(previousUrl), children: /* @__PURE__ */ jsx(Trans, { message: "Billing" }) }),
/* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(Trans, { message: "Renew" }) })
] }),
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold my-32 md:my-64", children: /* @__PURE__ */ jsx(Trans, { message: "Renew your plan" }) }),
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "max-w-[464px]", children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold", children: product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { price, className: "text-lg" }),
/* @__PURE__ */ jsx("div", { className: "text-base mt-12 border-b pb-24 mb-48", children: /* @__PURE__ */ jsx(
Trans,
{
message: "This plan will no longer be canceled. It will renew on :date",
values: { date: endDate }
}
) }),
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "w-full mb-16",
onClick: handleResumeSubscription,
disabled: resumeSubscription.isPending,
children: /* @__PURE__ */ jsx(Trans, { message: "Renew plan" })
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
className: "w-full",
to: previousUrl,
elementType: Link,
children: /* @__PURE__ */ jsx(Trans, { message: "Go back" })
}
),
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted mt-12", children: /* @__PURE__ */ jsx(Trans, { message: "By renewing your plan, you agree to our terms of service and privacy policy." }) })
] }) })
] });
}
function CancelledPlanPanel() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const endingDate = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: /* @__PURE__ */ jsx(FormattedDate, { preset: "long", date: subscription.ends_at }) });
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "mt-24 flex flex-col justify-between gap-20", children: [
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(
Chip,
{
className: "mb-10 w-min",
size: "xs",
radius: "rounded",
color: "danger",
children: /* @__PURE__ */ jsx(Trans, { message: "Canceled" })
}
),
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-bold", children: subscription.product.name }),
/* @__PURE__ */ jsx(FormattedPrice, { className: "mb-8 text-xl", price: subscription.price }),
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-8 text-base", children: [
/* @__PURE__ */ jsx(CalendarTodayIcon, { size: "sm", className: "text-muted" }),
/* @__PURE__ */ jsx("div", { className: "flex-auto", children: /* @__PURE__ */ jsx(
Trans,
{
message: "Your plan will be canceled on :date",
values: { date: endingDate }
}
) })
] })
] }),
/* @__PURE__ */ jsx("div", { className: "w-[233px]", children: /* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "mb-12 w-full",
elementType: Link,
to: "/billing/renew",
children: /* @__PURE__ */ jsx(Trans, { message: "Renew plan" })
}
) })
] }) });
}
function ActivePlanPanel() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const renewDate = /* @__PURE__ */ jsx(FormattedDate, { preset: "long", date: subscription.renews_at });
return /* @__PURE__ */ jsxs(Fragment, { children: [
subscription.past_due ? /* @__PURE__ */ jsx(PastDueMessage, {}) : null,
/* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Current plan" }), children: /* @__PURE__ */ jsxs("div", { className: "mt-24 flex justify-between gap-20", children: [
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-bold", children: subscription.product.name }),
/* @__PURE__ */ jsx(
FormattedPrice,
{
className: "mb-2 text-xl",
price: subscription.price
}
),
/* @__PURE__ */ jsx("div", { className: "text-base", children: /* @__PURE__ */ jsx(
Trans,
{
message: "Your plan renews on :date",
values: { date: renewDate }
}
) })
] }),
/* @__PURE__ */ jsxs("div", { className: "w-[233px]", children: [
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "mb-12 w-full",
elementType: Link,
to: "/billing/change-plan",
disabled: subscription.gateway_name === "none",
children: /* @__PURE__ */ jsx(Trans, { message: "Change plan" })
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outline",
color: "danger",
size: "md",
className: "w-full",
elementType: Link,
to: "/billing/cancel",
children: /* @__PURE__ */ jsx(Trans, { message: "Cancel plan" })
}
)
] })
] }) })
] });
}
function PastDueMessage() {
return /* @__PURE__ */ jsx(
SectionHelper,
{
className: "mb-24",
color: "danger",
title: "Payment is past due",
description: "Your recent recurring payment has failed with the payment method we have on file. Please update your payment method to avoid any service interruptions."
}
);
}
const paypalSvg = "/assets/paypal-c2a77c63.svg";
function PaymentMethodPanel() {
const { user, subscription } = useBillingUser();
if (!user || !subscription)
return null;
const isPaypal = subscription.gateway_name === "paypal";
const PaymentMethod = isPaypal ? PaypalPaymentMethod : CardPaymentMethod;
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Payment method" }), children: /* @__PURE__ */ jsx(
PaymentMethod,
{
methodClassName: "whitespace-nowrap text-base max-w-[464px] flex items-center gap-10",
linkClassName: "flex items-center gap-4 text-muted mt-18 block hover:underline"
}
) });
}
function CardPaymentMethod({
methodClassName,
linkClassName
}) {
const { user } = useBillingUser();
if (!user)
return null;
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { className: methodClassName, children: [
/* @__PURE__ */ jsx("span", { className: "capitalize", children: user.card_brand }),
" ••••",
user.card_last_four,
user.card_expires && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: /* @__PURE__ */ jsx(Trans, { message: "Expires :date", values: { date: user.card_expires } }) })
] }),
/* @__PURE__ */ jsxs(Link, { className: linkClassName, to: "/billing/change-payment-method", children: [
/* @__PURE__ */ jsx(EditIcon, { size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: "Change payment method" })
] })
] });
}
function PaypalPaymentMethod({
methodClassName,
linkClassName
}) {
const { subscription } = useBillingUser();
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("div", { className: methodClassName, children: /* @__PURE__ */ jsx(SvgImage, { src: paypalSvg }) }),
/* @__PURE__ */ jsxs(
"a",
{
className: linkClassName,
href: `https://www.sandbox.paypal.com/myaccount/autopay/connect/${subscription == null ? void 0 : subscription.gateway_id}/funding`,
target: "_blank",
rel: "noreferrer",
children: [
/* @__PURE__ */ jsx(EditIcon, { size: "sm" }),
/* @__PURE__ */ jsx(Trans, { message: "Change payment method" })
]
}
)
] });
}
const Endpoint = "billing/invoices";
function useInvoices(userId) {
return useQuery({
queryKey: [Endpoint],
queryFn: () => fetchInvoices(userId)
});
}
function fetchInvoices(userId) {
return apiClient.get(Endpoint, { params: { userId } }).then((response) => response.data);
}
function InvoiceHistoryPanel() {
var _a;
const { user } = useBillingUser();
const query = useInvoices(user == null ? void 0 : user.id);
if (!user)
return null;
const invoices = (_a = query.data) == null ? void 0 : _a.invoices;
return /* @__PURE__ */ jsx(BillingPlanPanel, { title: /* @__PURE__ */ jsx(Trans, { message: "Payment history" }), children: /* @__PURE__ */ jsx("div", { className: "max-w-[464px]", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: query.isLoading ? /* @__PURE__ */ jsx(LoadingSkeleton, {}, "loading-skeleton") : /* @__PURE__ */ jsx(InvoiceList, { invoices }, "invoices") }) }) });
}
function InvoiceList({ invoices }) {
const { base_url } = useSettings();
return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [
!(invoices == null ? void 0 : invoices.length) ? /* @__PURE__ */ jsx("div", { className: "text-muted italic", children: /* @__PURE__ */ jsx(Trans, { message: "No invoices yet" }) }) : void 0,
invoices == null ? void 0 : invoices.map((invoice) => {
var _a;
return /* @__PURE__ */ jsxs(
"div",
{
className: "whitespace-nowrap text-base flex items-center justify-between gap-10 mb-14",
children: [
/* @__PURE__ */ jsxs(
"a",
{
href: `${base_url}/billing/invoices/${invoice.uuid}`,
target: "_blank",
className: "flex items-center gap-8 hover:underline",
rel: "noreferrer",
children: [
/* @__PURE__ */ jsx(FormattedDate, { date: invoice.created_at }),
/* @__PURE__ */ jsx(OpenInNewIcon, { size: "xs" })
]
}
),
invoice.subscription.price && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
FormattedCurrency,
{
value: invoice.subscription.price.amount,
currency: invoice.subscription.price.currency
}
) }),
/* @__PURE__ */ jsx(
Chip,
{
size: "xs",
color: invoice.paid ? "positive" : "danger",
radius: "rounded",
children: invoice.paid ? /* @__PURE__ */ jsx(Trans, { message: "Paid" }) : /* @__PURE__ */ jsx(Trans, { message: "Unpaid" })
}
),
/* @__PURE__ */ jsx("div", { children: (_a = invoice.subscription.product) == null ? void 0 : _a.name })
]
},
invoice.id
);
})
] });
}
function LoadingSkeleton() {
return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-14" }),
/* @__PURE__ */ jsx(Skeleton, {})
] });
}
function BillingPage() {
const { subscription } = useBillingUser();
if (!(subscription == null ? void 0 : subscription.price) || !(subscription == null ? void 0 : subscription.product))
return null;
const planPanel = subscription.ends_at ? /* @__PURE__ */ jsx(CancelledPlanPanel, {}) : /* @__PURE__ */ jsx(ActivePlanPanel, {});
return /* @__PURE__ */ jsxs("div", { children: [
planPanel,
/* @__PURE__ */ jsx(PaymentMethodPanel, {}),
/* @__PURE__ */ jsx(InvoiceHistoryPanel, {})
] });
}
function BillingPageRoutes() {
return /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsxs(
Route,
{
path: "/",
element: /* @__PURE__ */ jsx(SubscribedRoute, { children: /* @__PURE__ */ jsx(BillingPageLayout, {}) }),
children: [
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(BillingPage, {}) }),
/* @__PURE__ */ jsxs(
Route,
{
path: "change-payment-method",
element: /* @__PURE__ */ jsx(ChangePaymentMethodLayout, {}),
children: [
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ChangePaymentMethodPage, {}) }),
/* @__PURE__ */ jsx(Route, { path: "done", element: /* @__PURE__ */ jsx(ChangePaymentMethodDone, {}) })
]
}
),
/* @__PURE__ */ jsx(Route, { path: "change-plan", element: /* @__PURE__ */ jsx(ChangePlanPage, {}) }),
/* @__PURE__ */ jsx(
Route,
{
path: "change-plan/:productId/:priceId/confirm",
element: /* @__PURE__ */ jsx(ConfirmPlanChangePage, {})
}
),
/* @__PURE__ */ jsx(Route, { path: "cancel", element: /* @__PURE__ */ jsx(ConfirmPlanCancellationPage, {}) }),
/* @__PURE__ */ jsx(Route, { path: "renew", element: /* @__PURE__ */ jsx(ConfirmPlanRenewalPage, {}) })
]
}
) });
}
export {
BillingPageRoutes as default
};
//# sourceMappingURL=billing-page-routes-d5e804d2.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,202 @@
import { jsxs, jsx } from "react/jsx-runtime";
import clsx from "clsx";
import { b6 as useAuth, bc as useIsDarkMode, aU as useSelectedLocale, u as useSettings, b as apiClient, B as Button, a2 as Skeleton, o as opacityAnimation, E as ErrorIcon, T as Trans } from "../server-entry.mjs";
import { useRef, useState, useEffect, Fragment } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Link } from "react-router-dom";
import { AnimatePresence, m } from "framer-motion";
import { T as TaskAltIcon } from "./TaskAlt-798b1c02.mjs";
function useStripe({ type, productId, priceId }) {
const { user } = useAuth();
const isDarkMode = useIsDarkMode();
const isInitiatedRef = useRef(false);
const paymentElementRef = useRef(null);
const { localeCode } = useSelectedLocale();
const [stripe, setStripe] = useState(null);
const [elements, setElements] = useState(null);
const {
branding: { site_name },
billing: {
stripe_public_key,
stripe: { enable }
}
} = useSettings();
useEffect(() => {
if (!enable || !stripe_public_key || isInitiatedRef.current)
return;
Promise.all([
// load stripe js library
loadStripe(stripe_public_key, {
apiVersion: "2022-08-01",
locale: localeCode
}),
// create partial subscription for clientSecret
type === "setupIntent" ? createSetupIntent() : createSubscription(productId, priceId)
]).then(([stripe2, { clientSecret }]) => {
if (stripe2 && paymentElementRef.current) {
const elements2 = stripe2.elements({
clientSecret,
appearance: {
theme: isDarkMode ? "night" : "stripe"
}
});
const paymentElement = elements2.create("payment", {
business: { name: site_name },
terms: { card: "never" },
fields: {
billingDetails: {
address: "auto"
}
},
defaultValues: {
billingDetails: {
email: user == null ? void 0 : user.email
}
}
});
paymentElement.mount(paymentElementRef.current);
setStripe(stripe2);
setElements(elements2);
}
});
isInitiatedRef.current = true;
}, [
productId,
stripe_public_key,
enable,
isDarkMode,
localeCode,
site_name,
type,
user == null ? void 0 : user.email
]);
return {
stripe,
elements,
paymentElementRef,
stripeIsEnabled: stripe_public_key != null && enable
};
}
function createSetupIntent() {
return apiClient.post("billing/stripe/create-setup-intent").then((r) => r.data);
}
function createSubscription(productId, priceId) {
return apiClient.post("billing/stripe/create-partial-subscription", {
product_id: productId,
price_id: priceId
}).then((r) => r.data);
}
function StripeElementsForm({
productId,
priceId,
type = "subscription",
submitLabel,
returnUrl
}) {
const { stripe, elements, paymentElementRef, stripeIsEnabled } = useStripe({
type,
productId,
priceId
});
const [errorMessage, setErrorMessage] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const stripeIsReady = !stripeIsEnabled || elements != null && stripe != null;
const handleSubmit = async (e) => {
var _a, _b;
e.preventDefault();
if (!stripe || !elements)
return;
setIsSubmitting(true);
try {
const method = type === "subscription" ? "confirmPayment" : "confirmSetup";
const result = await stripe[method]({
elements,
confirmParams: {
return_url: returnUrl
}
});
if (((_a = result.error) == null ? void 0 : _a.type) !== "validation_error" && ((_b = result.error) == null ? void 0 : _b.message)) {
setErrorMessage(result.error.message);
}
} catch {
}
setIsSubmitting(false);
};
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
/* @__PURE__ */ jsx(
"div",
{
ref: paymentElementRef,
className: clsx("min-h-[303px]", !stripeIsEnabled && "hidden"),
children: stripeIsEnabled && /* @__PURE__ */ jsx(StripeSkeleton, {})
}
),
errorMessage && !isSubmitting && /* @__PURE__ */ jsx("div", { className: "mt-20 text-danger", children: errorMessage }),
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
size: "md",
className: "mt-40 w-full",
type: "submit",
disabled: isSubmitting || !stripeIsReady,
children: submitLabel
}
)
] });
}
function StripeSkeleton() {
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Skeleton, { className: "mb-20 h-30" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-20 h-30" }),
/* @__PURE__ */ jsx(Skeleton, { className: "mb-20 h-30" }),
/* @__PURE__ */ jsx(Skeleton, { className: "h-30" })
] });
}
function BillingRedirectMessage({ config }) {
return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: /* @__PURE__ */ jsx("div", { className: "mt-80", children: config ? /* @__PURE__ */ jsxs(
m.div,
{
className: "text-center",
...opacityAnimation,
children: [
config.status === "success" ? /* @__PURE__ */ jsx(TaskAltIcon, { className: "text-positive text-6xl" }) : /* @__PURE__ */ jsx(ErrorIcon, { className: "text-danger text-6xl" }),
/* @__PURE__ */ jsx("div", { className: "text-2xl font-semibold mt-30", children: /* @__PURE__ */ jsx(Trans, { ...config.message }) }),
/* @__PURE__ */ jsx(
Button,
{
variant: "flat",
color: "primary",
className: "w-full mt-30",
size: "md",
elementType: Link,
to: config.link,
children: /* @__PURE__ */ jsx(Trans, { ...config.buttonLabel })
}
)
]
},
"payment-status"
) : /* @__PURE__ */ jsx(LoadingSkeleton, {}, "loading-skeleton") }) });
}
function LoadingSkeleton() {
return /* @__PURE__ */ jsxs(
m.div,
{
className: "text-center max-w-280",
...opacityAnimation,
children: [
/* @__PURE__ */ jsx(Skeleton, { size: "w-50 h-50", variant: "rect" }),
/* @__PURE__ */ jsx(Skeleton, { className: "text-2xl mt-30" }),
/* @__PURE__ */ jsx(Skeleton, { size: "h-42", className: "mt-30" })
]
},
"loading-skeleton"
);
}
export {
BillingRedirectMessage as B,
StripeElementsForm as S
};
//# sourceMappingURL=billing-redirect-message-d4e5c39f.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,437 @@
import { jsx, jsxs } from "react/jsx-runtime";
import { Navigate, Outlet, useParams, useSearchParams, Routes, Route } from "react-router-dom";
import { b6 as useAuth, bq as removeFromLocalStorage, l as StaticPageTitle, T as Trans, N as Navbar, C as CustomMenu, br as LocaleSwitcher, b as apiClient, aB as FormattedPrice, bs as ProductFeatureList, b8 as FormattedCurrency, o as opacityAnimation, a2 as Skeleton, aA as useProducts, u as useSettings, ac as FullPageLoader, ab as useBootstrapData, aa as useNavigate, m as message } from "../server-entry.mjs";
import { useEffect, Fragment, useRef, useState } from "react";
import { useQuery, keepPreviousData } from "@tanstack/react-query";
import { m } from "framer-motion";
import { loadScript } from "@paypal/paypal-js";
import { S as StripeElementsForm, B as BillingRedirectMessage } from "./billing-redirect-message-d4e5c39f.mjs";
import { loadStripe } from "@stripe/stripe-js";
import "react-dom/server";
import "process";
import "http";
import "axios";
import "react-router-dom/server.mjs";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
import "./TaskAlt-798b1c02.mjs";
function NotSubscribedRoute({ children }) {
const { isLoggedIn, isSubscribed } = useAuth();
if (!isLoggedIn) {
return /* @__PURE__ */ jsx(Navigate, { to: "/register", replace: true });
}
if (isLoggedIn && isSubscribed) {
return /* @__PURE__ */ jsx(Navigate, { to: "/billing", replace: true });
}
return children || /* @__PURE__ */ jsx(Outlet, {});
}
function CheckoutLayout({ children }) {
const [left, right] = children;
useEffect(() => {
removeFromLocalStorage("be.onboarding.selected");
}, []);
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(StaticPageTitle, { children: /* @__PURE__ */ jsx(Trans, { message: "Checkout" }) }),
/* @__PURE__ */ jsx(
Navbar,
{
size: "sm",
color: "transparent",
className: "z-10 mb-20 md:mb-0",
textColor: "text-main",
logoColor: "dark",
darkModeColor: "transparent",
menuPosition: "checkout-page-navbar"
}
),
/* @__PURE__ */ jsxs("div", { className: "md:flex w-full mx-auto justify-between px-20 md:px-0 md:pt-128 md:max-w-950", children: [
/* @__PURE__ */ jsx("div", { className: "hidden md:block fixed right-0 top-0 w-1/2 h-full bg-alt shadow-[15px_0_30px_0_rgb(0_0_0_/_18%)]" }),
/* @__PURE__ */ jsxs("div", { className: "md:w-400 overflow-hidden", children: [
left,
/* @__PURE__ */ jsx(
CustomMenu,
{
menu: "checkout-page-footer",
className: "text-xs mt-50 text-muted overflow-x-auto"
}
),
/* @__PURE__ */ jsx("div", { className: "mt-40", children: /* @__PURE__ */ jsx(LocaleSwitcher, {}) })
] }),
/* @__PURE__ */ jsx("div", { className: "hidden md:block w-384", children: /* @__PURE__ */ jsx("div", { className: "relative z-10", children: right }) })
] })
] });
}
const endpoint = (productId) => `billing/products/${productId}`;
function useCheckoutProduct() {
var _a;
const { productId, priceId } = useParams();
const query = useQuery({
queryKey: [endpoint(productId)],
queryFn: () => fetchProduct(productId),
placeholderData: keepPreviousData,
enabled: productId != null && priceId != null
});
const product = (_a = query.data) == null ? void 0 : _a.product;
const price = (product == null ? void 0 : product.prices.find((p) => p.id === parseInt(priceId))) || (product == null ? void 0 : product.prices[0]);
return { status: query.status, product, price };
}
function fetchProduct(productId) {
return apiClient.get(endpoint(productId)).then((response) => response.data);
}
function CheckoutProductSummary({
showBillingLine = true
}) {
const { status, product, price } = useCheckoutProduct();
if (status === "error" || status !== "pending" && (!product || !price)) {
return null;
}
return /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx("h2", { className: "text-2xl mb-30", children: /* @__PURE__ */ jsx(Trans, { message: "Summary" }) }),
status === "pending" ? /* @__PURE__ */ jsx(LoadingSkeleton, {}, "loading-skeleton") : /* @__PURE__ */ jsx(
ProductSummary,
{
product,
price,
showBillingLine
}
)
] });
}
function ProductSummary({
product,
price,
showBillingLine
}) {
return /* @__PURE__ */ jsxs(m.div, { children: [
/* @__PURE__ */ jsx("div", { className: "text-xl font-semibold mb-6", children: product.name }),
product.description && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted", children: product.description }),
/* @__PURE__ */ jsx(
FormattedPrice,
{
priceClassName: "font-bold text-4xl",
periodClassName: "text-muted text-xs",
variant: "separateLine",
price,
className: "mt-32"
}
),
/* @__PURE__ */ jsx(ProductFeatureList, { product }),
showBillingLine && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-24 border-t pt-24 mt-32 font-medium", children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Trans, { message: "Billed today" }) }),
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(FormattedCurrency, { value: price.amount, currency: price.currency }) })
] })
] });
}
function LoadingSkeleton() {
return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, className: "max-w-180", children: [
/* @__PURE__ */ jsx(Skeleton, { className: "text-xl mb-6" }),
/* @__PURE__ */ jsx(Skeleton, { className: "text-sm" }),
/* @__PURE__ */ jsx(Skeleton, { className: "text-4xl mt-32" })
] });
}
function usePaypal({ productId, priceId }) {
const { data } = useProducts();
const paypalLoadStarted = useRef(false);
const paypalButtonsRendered = useRef(false);
const [paypalIsLoaded, setPaypalIsLoaded] = useState(false);
const paypalElementRef = useRef(null);
const {
base_url,
billing: {
stripe: { enable: stripeEnabled },
paypal: { enable: paypalEnabled, public_key }
}
} = useSettings();
useEffect(() => {
if (!paypalEnabled || !public_key || paypalLoadStarted.current)
return;
loadScript({
clientId: public_key,
intent: "subscription",
vault: true,
disableFunding: stripeEnabled ? "card" : void 0
}).then(() => {
setPaypalIsLoaded(true);
});
paypalLoadStarted.current = true;
}, [public_key, paypalEnabled, stripeEnabled]);
useEffect(() => {
var _a;
if (!paypalIsLoaded || !((_a = window.paypal) == null ? void 0 : _a.Buttons) || !paypalElementRef.current || !(data == null ? void 0 : data.products.length) || !productId || !priceId || paypalButtonsRendered.current)
return;
const product = data.products.find((p) => p.id === parseInt(productId));
const price = product == null ? void 0 : product.prices.find((p) => p.id === parseInt(priceId));
window.paypal.Buttons({
style: {
label: "pay"
},
createSubscription: (data2, actions) => {
return actions.subscription.create({
application_context: {
shipping_preference: "NO_SHIPPING"
},
plan_id: price == null ? void 0 : price.paypal_id
});
},
onApprove: (data2, actions) => {
actions.redirect(
`${base_url}/checkout/${productId}/${priceId}/paypal/done?subscriptionId=${data2.subscriptionID}&status=success`
);
return Promise.resolve();
},
onError: (e) => {
location.href = `${base_url}/checkout/${productId}/${priceId}/paypal/done?status=error`;
}
}).render(paypalElementRef.current).then(() => {
paypalButtonsRendered.current = true;
});
}, [productId, priceId, data, paypalIsLoaded, base_url]);
return {
paypalElementRef,
stripeIsEnabled: public_key != null && paypalEnabled
};
}
function Checkout() {
var _a;
const { productId, priceId } = useParams();
const productQuery = useProducts();
const { paypalElementRef } = usePaypal({
productId,
priceId
});
const {
base_url,
billing: { stripe }
} = useSettings();
if (productQuery.isLoading) {
return /* @__PURE__ */ jsx(FullPageLoader, { screen: true });
}
const product = (_a = productQuery.data) == null ? void 0 : _a.products.find(
(p) => p.id === parseInt(productId)
);
const price = product == null ? void 0 : product.prices.find((p) => p.id === parseInt(priceId));
if (!product || !price || productQuery.status === "error") {
return /* @__PURE__ */ jsx(Navigate, { to: "/pricing", replace: true });
}
return /* @__PURE__ */ jsxs(CheckoutLayout, { children: [
/* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("h1", { className: "mb-40 text-4xl", children: /* @__PURE__ */ jsx(Trans, { message: "Checkout" }) }),
stripe.enable ? /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
StripeElementsForm,
{
productId,
priceId,
submitLabel: /* @__PURE__ */ jsx(Trans, { message: "Upgrade" }),
type: "subscription",
returnUrl: `${base_url}/checkout/${productId}/${priceId}/stripe/done`
}
),
/* @__PURE__ */ jsx(Separator, {})
] }) : null,
/* @__PURE__ */ jsx("div", { ref: paypalElementRef }),
/* @__PURE__ */ jsx("div", { className: "mt-30 text-xs text-muted", children: /* @__PURE__ */ jsx(Trans, { message: "Youll be charged until you cancel your subscription. Previous charges wont be refunded when you cancel unless its legally required. Your payment data is encrypted and secure. By subscribing your agree to our terms of service and privacy policy." }) })
] }),
/* @__PURE__ */ jsx(CheckoutProductSummary, {})
] });
}
function Separator() {
return /* @__PURE__ */ jsx("div", { className: "relative my-20 text-center before:absolute before:left-0 before:top-1/2 before:h-1 before:w-full before:-translate-y-1/2 before:bg-divider", children: /* @__PURE__ */ jsx("span", { className: "relative z-10 bg px-10 text-sm text-muted", children: /* @__PURE__ */ jsx(Trans, { message: "or" }) }) });
}
function CheckoutStripeDone() {
const { invalidateBootstrapData } = useBootstrapData();
const { productId, priceId } = useParams();
const navigate = useNavigate();
const {
billing: { stripe_public_key }
} = useSettings();
const [params] = useSearchParams();
const clientSecret = params.get("payment_intent_client_secret");
const [messageConfig, setMessageConfig] = useState();
const stripeInitiated = useRef();
useEffect(() => {
if (stripeInitiated.current)
return;
loadStripe(stripe_public_key).then(async (stripe) => {
if (!stripe || !clientSecret) {
setMessageConfig(getRedirectMessageConfig$1());
return;
}
stripe.retrievePaymentIntent(clientSecret).then(async ({ paymentIntent }) => {
if ((paymentIntent == null ? void 0 : paymentIntent.status) === "succeeded") {
await storeSubscriptionDetailsLocally$1(paymentIntent.id);
setMessageConfig(
getRedirectMessageConfig$1("succeeded", productId, priceId)
);
window.location.href = "/billing";
} else {
setMessageConfig(
getRedirectMessageConfig$1(
paymentIntent == null ? void 0 : paymentIntent.status,
productId,
priceId
)
);
}
});
});
stripeInitiated.current = true;
}, [
stripe_public_key,
clientSecret,
priceId,
productId,
invalidateBootstrapData
]);
if (!clientSecret) {
navigate("/");
return null;
}
return /* @__PURE__ */ jsxs(CheckoutLayout, { children: [
/* @__PURE__ */ jsx(BillingRedirectMessage, { config: messageConfig }),
/* @__PURE__ */ jsx(CheckoutProductSummary, { showBillingLine: false })
] });
}
function getRedirectMessageConfig$1(status, productId, priceId) {
switch (status) {
case "succeeded":
return {
message: message("Subscription successful!"),
status: "success",
buttonLabel: message("Return to site"),
link: "/billing"
};
case "processing":
return {
message: message(
"Payment processing. We'll update you when payment is received."
),
status: "success",
buttonLabel: message("Return to site"),
link: "/billing"
};
case "requires_payment_method":
return {
message: message("Payment failed. Please try another payment method."),
status: "error",
buttonLabel: message("Go back"),
link: errorLink$1(productId, priceId)
};
default:
return {
message: message("Something went wrong"),
status: "error",
buttonLabel: message("Go back"),
link: errorLink$1(productId, priceId)
};
}
}
function errorLink$1(productId, priceId) {
return productId && priceId ? `/checkout/${productId}/${priceId}` : "/";
}
function storeSubscriptionDetailsLocally$1(paymentIntentId) {
return apiClient.post("billing/stripe/store-subscription-details-locally", {
payment_intent_id: paymentIntentId
});
}
function CheckoutPaypalDone() {
const { invalidateBootstrapData } = useBootstrapData();
const { productId, priceId } = useParams();
const [params] = useSearchParams();
const [messageConfig, setMessageConfig] = useState();
useEffect(() => {
const subscriptionId = params.get("subscriptionId");
const status = params.get("status");
if (subscriptionId && status === "success") {
storeSubscriptionDetailsLocally(subscriptionId).then(() => {
setMessageConfig(
getRedirectMessageConfig("success", productId, priceId)
);
window.location.href = "/billing";
});
} else {
setMessageConfig(getRedirectMessageConfig(status, productId, priceId));
}
}, [priceId, productId, params, invalidateBootstrapData]);
return /* @__PURE__ */ jsxs(CheckoutLayout, { children: [
/* @__PURE__ */ jsx(BillingRedirectMessage, { config: messageConfig }),
/* @__PURE__ */ jsx(CheckoutProductSummary, { showBillingLine: false })
] });
}
function getRedirectMessageConfig(status, productId, priceId) {
switch (status) {
case "success":
return {
message: message("Subscription successful!"),
status: "success",
buttonLabel: message("Return to site"),
link: "/billing"
};
default:
return {
message: message("Something went wrong. Please try again."),
status: "error",
buttonLabel: message("Go back"),
link: errorLink(productId, priceId)
};
}
}
function errorLink(productId, priceId) {
return productId && priceId ? `/checkout/${productId}/${priceId}` : "/";
}
function storeSubscriptionDetailsLocally(subscriptionId) {
return apiClient.post("billing/paypal/store-subscription-details-locally", {
paypal_subscription_id: subscriptionId
});
}
function CheckoutRoutes() {
return /* @__PURE__ */ jsxs(Routes, { children: [
/* @__PURE__ */ jsx(
Route,
{
path: ":productId/:priceId",
element: /* @__PURE__ */ jsx(NotSubscribedRoute, { children: /* @__PURE__ */ jsx(Checkout, {}) })
}
),
/* @__PURE__ */ jsx(
Route,
{
path: ":productId/:priceId/stripe/done",
element: /* @__PURE__ */ jsx(NotSubscribedRoute, { children: /* @__PURE__ */ jsx(CheckoutStripeDone, {}) })
}
),
/* @__PURE__ */ jsx(
Route,
{
path: ":productId/:priceId/paypal/done",
element: /* @__PURE__ */ jsx(NotSubscribedRoute, { children: /* @__PURE__ */ jsx(CheckoutPaypalDone, {}) })
}
)
] });
}
export {
CheckoutRoutes as default
};
//# sourceMappingURL=checkout-routes-1a4f252c.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,139 @@
import { jsx } from "react/jsx-runtime";
import { useContext, useRef, useState, useCallback, useEffect } from "react";
import { bJ as PlayerStoreContext, bK as usePlayerStore, bL as useHtmlMediaInternalState, bM as useHtmlMediaEvents, bN as useHtmlMediaApi } from "./user-profile-link-0bca566c.mjs";
import { supportsMediaSource, MediaPlayer } from "dashjs";
import "../server-entry.mjs";
import "react-dom/server";
import "process";
import "http";
import "@tanstack/react-query";
import "axios";
import "react-router-dom/server.mjs";
import "framer-motion";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "react-router-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
import "./OpenInNew-3b47a656.mjs";
import "fscreen";
import "zustand/middleware";
import "zustand/traditional";
import "@react-aria/interactions";
function DashProvider() {
const store = useContext(PlayerStoreContext);
const cuedMedia = usePlayerStore((s) => s.cuedMedia);
const videoRef = useRef(null);
const htmlMediaState = useHtmlMediaInternalState(videoRef);
const htmlMediaEvents = useHtmlMediaEvents(htmlMediaState);
const htmlMediaApi = useHtmlMediaApi(htmlMediaState);
const dash = useRef();
const [dashReady, setDashReady] = useState(false);
const destroyDash = useCallback(() => {
if (dash.current) {
dash.current.destroy();
dash.current = void 0;
setDashReady(false);
}
}, []);
const setupDash = useCallback(() => {
if (!supportsMediaSource()) {
store.getState().emit("error", { fatal: true });
return;
}
const dashInstance = MediaPlayer().create();
dashInstance.on(MediaPlayer.events.ERROR, (e) => {
store.getState().emit("error", { sourceEvent: e });
});
dashInstance.on(MediaPlayer.events.PLAYBACK_METADATA_LOADED, () => {
const levels = dashInstance.getBitrateInfoListFor("video");
if (!(levels == null ? void 0 : levels.length))
return;
store.getState().emit("playbackQualities", {
qualities: ["auto", ...levels.map(levelToPlaybackQuality)]
});
store.getState().emit("playbackQualityChange", { quality: "auto" });
});
dashInstance.initialize(videoRef.current, void 0, false);
dash.current = dashInstance;
setDashReady(true);
}, [store]);
useEffect(() => {
setupDash();
return () => {
destroyDash();
};
}, [setupDash, destroyDash]);
useEffect(() => {
if (dash.current && (cuedMedia == null ? void 0 : cuedMedia.src)) {
dash.current.attachSource(cuedMedia.src);
}
}, [cuedMedia == null ? void 0 : cuedMedia.src, dashReady]);
useEffect(() => {
if (!dashReady)
return;
store.setState({
providerApi: {
...htmlMediaApi,
setPlaybackQuality: (quality) => {
if (!dash.current)
return;
const levels = dash.current.getBitrateInfoListFor("video");
const index = levels.findIndex(
(level) => levelToPlaybackQuality(level) === quality
);
dash.current.updateSettings({
streaming: {
abr: {
autoSwitchBitrate: {
video: index === -1
}
}
}
});
if (index >= 0) {
dash.current.setQualityFor("video", index);
}
store.getState().emit("playbackQualityChange", { quality });
}
}
});
}, [store, htmlMediaApi, dashReady]);
return /* @__PURE__ */ jsx(
"video",
{
className: "h-full w-full",
ref: videoRef,
playsInline: true,
poster: cuedMedia == null ? void 0 : cuedMedia.poster,
...htmlMediaEvents
}
);
}
const levelToPlaybackQuality = (level) => {
return level === -1 ? "auto" : `${level.height}p`;
};
export {
DashProvider as default
};
//# sourceMappingURL=dash-provider-0e5b2c0e.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
import hljs from "highlight.js/lib/core";
import { default as default2 } from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import typescript from "highlight.js/lib/languages/typescript";
import html from "highlight.js/lib/languages/xml";
import css from "highlight.js/lib/languages/css";
import php from "highlight.js/lib/languages/php";
import shell from "highlight.js/lib/languages/shell";
import bash from "highlight.js/lib/languages/bash";
import ruby from "highlight.js/lib/languages/ruby";
import python from "highlight.js/lib/languages/python";
import java from "highlight.js/lib/languages/java";
import c from "highlight.js/lib/languages/c";
const githubTheme = "";
const githubDarkTheme = "";
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("typescript", typescript);
hljs.registerLanguage("html", html);
hljs.registerLanguage("css", css);
hljs.registerLanguage("php", php);
hljs.registerLanguage("shell", shell);
hljs.registerLanguage("bash", bash);
hljs.registerLanguage("ruby", ruby);
hljs.registerLanguage("python", python);
hljs.registerLanguage("java", java);
hljs.registerLanguage("c", c);
export {
default2 as hljs
};
//# sourceMappingURL=highlight-31acaf62.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"highlight-31acaf62.mjs","sources":["../../../common/resources/client/text-editor/highlight/highlight.ts"],"sourcesContent":["import hljs from 'highlight.js/lib/core';\n\n// load specific languages only\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport html from 'highlight.js/lib/languages/xml';\nimport css from 'highlight.js/lib/languages/css';\nimport php from 'highlight.js/lib/languages/php';\nimport shell from 'highlight.js/lib/languages/shell';\nimport bash from 'highlight.js/lib/languages/bash';\nimport ruby from 'highlight.js/lib/languages/ruby';\nimport python from 'highlight.js/lib/languages/python';\nimport java from 'highlight.js/lib/languages/java';\nimport c from 'highlight.js/lib/languages/c';\n\n// load css\nimport './github-theme.css';\nimport './github-dark-theme.css';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('html', html);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('php', php);\nhljs.registerLanguage('shell', shell);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('ruby', ruby);\nhljs.registerLanguage('python', python);\nhljs.registerLanguage('java', java);\nhljs.registerLanguage('c', c);\n\nexport {hljs};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAmBA,KAAK,iBAAiB,cAAc,UAAU;AAC9C,KAAK,iBAAiB,cAAc,UAAU;AAC9C,KAAK,iBAAiB,QAAQ,IAAI;AAClC,KAAK,iBAAiB,OAAO,GAAG;AAChC,KAAK,iBAAiB,OAAO,GAAG;AAChC,KAAK,iBAAiB,SAAS,KAAK;AACpC,KAAK,iBAAiB,QAAQ,IAAI;AAClC,KAAK,iBAAiB,QAAQ,IAAI;AAClC,KAAK,iBAAiB,UAAU,MAAM;AACtC,KAAK,iBAAiB,QAAQ,IAAI;AAClC,KAAK,iBAAiB,KAAK,CAAC;"}

View File

@@ -0,0 +1,176 @@
import { jsx } from "react/jsx-runtime";
import { useContext, useRef, useState, useCallback, useEffect } from "react";
import { bJ as PlayerStoreContext, bK as usePlayerStore, bL as useHtmlMediaInternalState, bM as useHtmlMediaEvents, bN as useHtmlMediaApi } from "./user-profile-link-0bca566c.mjs";
import Hls from "hls.js";
import "../server-entry.mjs";
import "react-dom/server";
import "process";
import "http";
import "@tanstack/react-query";
import "axios";
import "react-router-dom/server.mjs";
import "framer-motion";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "react-router-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
import "./OpenInNew-3b47a656.mjs";
import "fscreen";
import "zustand/middleware";
import "zustand/traditional";
import "@react-aria/interactions";
function HlsProvider() {
const store = useContext(PlayerStoreContext);
const cuedMedia = usePlayerStore((s) => s.cuedMedia);
const videoRef = useRef(null);
const htmlMediaState = useHtmlMediaInternalState(videoRef);
const htmlMediaEvents = useHtmlMediaEvents(htmlMediaState);
const htmlMediaApi = useHtmlMediaApi(htmlMediaState);
const hls = useRef();
const [hlsReady, setHlsReady] = useState(false);
const destroyHls = useCallback(() => {
var _a;
if (hls) {
(_a = hls.current) == null ? void 0 : _a.destroy();
hls.current = void 0;
setHlsReady(false);
}
}, []);
const setupHls = useCallback(() => {
if (!Hls.isSupported()) {
store.getState().emit("error", { fatal: true });
return;
}
const hlsInstance = new Hls({
startLevel: -1
});
hlsInstance.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
hlsInstance.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
hlsInstance.recoverMediaError();
break;
default:
destroyHls();
break;
}
}
store.getState().emit("error", { sourceEvent: data, fatal: data.fatal });
});
hlsInstance.on(Hls.Events.MANIFEST_PARSED, () => {
var _a;
if (!((_a = hlsInstance.levels) == null ? void 0 : _a.length))
return;
store.getState().emit("playbackQualities", {
qualities: ["auto", ...hlsInstance.levels.map(levelToPlaybackQuality)]
});
store.getState().emit("playbackQualityChange", { quality: "auto" });
});
hlsInstance.on(Hls.Events.AUDIO_TRACK_SWITCHED, (eventType, data) => {
const track = store.getState().audioTracks.find((t) => t.id === data.id);
if (track) {
store.getState().emit("currentAudioTrackChange", { trackId: track.id });
}
});
hlsInstance.on(
Hls.Events.LEVEL_LOADED,
(eventType, data) => {
var _a;
if (!store.getState().providerReady) {
const { type, live, totalduration: duration } = data.details;
const inferredStreamType = live ? type === "EVENT" && Number.isFinite(duration) ? "live:dvr" : "live" : "on-demand";
store.getState().emit("streamTypeChange", {
streamType: ((_a = store.getState().cuedMedia) == null ? void 0 : _a.streamType) || inferredStreamType
});
store.getState().emit("durationChange", { duration });
const audioTracks = hlsInstance.audioTracks.map(
(track) => ({
id: track.id,
label: track.name,
language: track.lang || "",
kind: "main"
})
);
store.getState().emit("audioTracks", { tracks: audioTracks });
}
}
);
hlsInstance.attachMedia(videoRef.current);
hls.current = hlsInstance;
setHlsReady(true);
}, [destroyHls, store]);
useEffect(() => {
setupHls();
return () => {
destroyHls();
};
}, [setupHls, destroyHls]);
useEffect(() => {
if (hls.current && (cuedMedia == null ? void 0 : cuedMedia.src) && hls.current.url !== (cuedMedia == null ? void 0 : cuedMedia.src)) {
hls.current.loadSource(cuedMedia.src);
}
}, [cuedMedia == null ? void 0 : cuedMedia.src, hlsReady]);
useEffect(() => {
if (!hlsReady)
return;
store.setState({
providerApi: {
...htmlMediaApi,
setCurrentAudioTrack: (trackId) => {
if (!hls.current)
return;
hls.current.audioTrack = trackId;
},
setPlaybackQuality: (quality) => {
if (!hls.current)
return;
hls.current.currentLevel = hls.current.levels.findIndex(
(level) => levelToPlaybackQuality(level) === quality
);
store.getState().emit("playbackQualityChange", { quality });
}
}
});
}, [htmlMediaApi, store, hlsReady]);
return /* @__PURE__ */ jsx(
"video",
{
className: "h-full w-full",
ref: videoRef,
playsInline: true,
poster: cuedMedia == null ? void 0 : cuedMedia.poster,
...htmlMediaEvents
}
);
}
const levelToPlaybackQuality = (level) => {
return level === -1 ? "auto" : `${level.height}p`;
};
export {
HlsProvider as default
};
//# sourceMappingURL=hls-provider-66ccc1f9.mjs.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,73 @@
import { jsx } from "react/jsx-runtime";
import { Chart, LineElement, PointElement, BarElement, ArcElement, LineController, BarController, PolarAreaController, RadialLinearScale, CategoryScale, LinearScale, Tooltip, Filler, Legend } from "chart.js";
import { useRef, useEffect } from "react";
import deepMerge from "deepmerge";
Chart.register([
LineElement,
PointElement,
BarElement,
ArcElement,
LineController,
BarController,
PolarAreaController,
RadialLinearScale,
CategoryScale,
LinearScale,
Tooltip,
Filler,
Legend
]);
function LazyChart({
type,
data,
options,
hideLegend
}) {
const ref = useRef(null);
const chartRef = useRef();
useEffect(() => {
if (ref.current) {
chartRef.current = new Chart(ref.current, {
type,
data,
options: deepMerge(
{
maintainAspectRatio: false,
animation: {
duration: 250
},
plugins: {
legend: {
position: "bottom",
display: !hideLegend
},
tooltip: {
padding: 16,
cornerRadius: 4,
callbacks: {
title: ([item]) => {
const data2 = item.raw;
return data2.tooltipTitle ?? item.label;
},
label: (item) => {
return ` ${item.dataset.label}: ${item.formattedValue}`;
}
}
}
}
},
options
)
});
}
return () => {
var _a;
(_a = chartRef.current) == null ? void 0 : _a.destroy();
};
}, [data, type, options, hideLegend]);
return /* @__PURE__ */ jsx("canvas", { ref });
}
export {
LazyChart as default
};
//# sourceMappingURL=lazy-chart-9300132f.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"lazy-chart-9300132f.mjs","sources":["../../../common/resources/client/charts/lazy-chart.tsx"],"sourcesContent":["import {\n ArcElement,\n BarController,\n BarElement,\n CategoryScale,\n Chart,\n ChartOptions,\n ChartType,\n Filler,\n Legend,\n LinearScale,\n LineController,\n LineElement,\n PointElement,\n PolarAreaController,\n RadialLinearScale,\n Tooltip,\n} from 'chart.js';\nimport {useEffect, useRef} from 'react';\nimport {BaseChartProps} from './base-chart';\nimport {FormattedDatasetItem} from './data/formatted-dataset-item';\nimport deepMerge from 'deepmerge';\n\nChart.register([\n LineElement,\n PointElement,\n BarElement,\n ArcElement,\n LineController,\n BarController,\n PolarAreaController,\n RadialLinearScale,\n CategoryScale,\n LinearScale,\n Tooltip,\n Filler,\n Legend,\n]);\n\nexport default function LazyChart({\n type,\n data,\n options,\n hideLegend,\n}: Omit<BaseChartProps<any>, 'children'>) {\n const ref = useRef<HTMLCanvasElement>(null);\n const chartRef = useRef<Chart<ChartType, unknown>>();\n\n useEffect(() => {\n if (ref.current) {\n chartRef.current = new Chart(ref.current, {\n type,\n data,\n options: deepMerge(\n {\n maintainAspectRatio: false,\n animation: {\n duration: 250,\n },\n plugins: {\n legend: {\n position: 'bottom',\n display: !hideLegend,\n },\n tooltip: {\n padding: 16,\n cornerRadius: 4,\n callbacks: {\n title: ([item]) => {\n const data = item.raw as FormattedDatasetItem;\n return data.tooltipTitle ?? item.label;\n },\n label: item => {\n return ` ${item.dataset.label}: ${item.formattedValue}`;\n },\n },\n },\n },\n },\n options as ChartOptions\n ),\n });\n }\n\n return () => {\n chartRef.current?.destroy();\n };\n }, [data, type, options, hideLegend]);\n\n return <canvas ref={ref}></canvas>;\n}\n"],"names":["data"],"mappings":";;;;AAuBA,MAAM,SAAS;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAwB,UAAU;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AAClC,QAAA,MAAM,OAA0B,IAAI;AAC1C,QAAM,WAAW;AAEjB,YAAU,MAAM;AACd,QAAI,IAAI,SAAS;AACf,eAAS,UAAU,IAAI,MAAM,IAAI,SAAS;AAAA,QACxC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,UACP;AAAA,YACE,qBAAqB;AAAA,YACrB,WAAW;AAAA,cACT,UAAU;AAAA,YACZ;AAAA,YACA,SAAS;AAAA,cACP,QAAQ;AAAA,gBACN,UAAU;AAAA,gBACV,SAAS,CAAC;AAAA,cACZ;AAAA,cACA,SAAS;AAAA,gBACP,SAAS;AAAA,gBACT,cAAc;AAAA,gBACd,WAAW;AAAA,kBACT,OAAO,CAAC,CAAC,IAAI,MAAM;AACjB,0BAAMA,QAAO,KAAK;AACXA,2BAAAA,MAAK,gBAAgB,KAAK;AAAA,kBACnC;AAAA,kBACA,OAAO,CAAQ,SAAA;AACb,2BAAO,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,cAAc;AAAA,kBACxD;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,QACF;AAAA,MAAA,CACD;AAAA,IACH;AAEA,WAAO,MAAM;;AACX,qBAAS,YAAT,mBAAkB;AAAA,IAAQ;AAAA,KAE3B,CAAC,MAAM,MAAM,SAAS,UAAU,CAAC;AAE7B,SAAA,oBAAC,YAAO,IAAU,CAAA;AAC3B;"}

View File

@@ -0,0 +1,78 @@
import { useMutation } from "@tanstack/react-query";
import { i as useTrans, t as toast, m as message, n as showHttpErrorToast, b as apiClient, I as IconButton, O as CloseIcon } from "../server-entry.mjs";
import { jsxs, jsx } from "react/jsx-runtime";
import clsx from "clsx";
function useCancelSubscription() {
const { trans } = useTrans();
return useMutation({
mutationFn: (props) => cancelSubscription(props),
onSuccess: (response, payload) => {
toast(
payload.delete ? trans(message("Subscription deleted.")) : trans(message("Subscription cancelled."))
);
},
onError: (err) => showHttpErrorToast(err)
});
}
function cancelSubscription({
subscriptionId,
...payload
}) {
return apiClient.post(`billing/subscriptions/${subscriptionId}/cancel`, payload).then((r) => r.data);
}
function useResumeSubscription() {
const { trans } = useTrans();
return useMutation({
mutationFn: (props) => resumeSubscription(props),
onSuccess: () => {
toast(trans(message("Subscription renewed.")));
},
onError: (err) => showHttpErrorToast(err)
});
}
function resumeSubscription({ subscriptionId }) {
return apiClient.post(`billing/subscriptions/${subscriptionId}/resume`).then((r) => r.data);
}
function SectionHelper({
title,
description,
actions,
color = "primary",
className,
size = "md",
leadingIcon,
onClose
}) {
return /* @__PURE__ */ jsxs(
"div",
{
className: clsx(
className,
"rounded-panel px-10 pb-10",
leadingIcon || onClose ? "py-4" : "py-10",
size === "sm" ? "text-xs" : "text-sm",
color === "positive" && "bg-positive/focus",
color === "warning" && "bg-warning/focus",
color === "danger" && "bg-danger/focus",
color === "primary" && "bg-primary/focus",
color === "neutral" && "border bg",
color === "bgAlt" && "border bg-alt"
),
children: [
title && /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-6", children: [
leadingIcon,
/* @__PURE__ */ jsx("div", { className: "font-medium", children: title }),
onClose ? /* @__PURE__ */ jsx(IconButton, { size: "xs", className: "ml-auto", onClick: () => onClose(), children: /* @__PURE__ */ jsx(CloseIcon, {}) }) : null
] }),
description && /* @__PURE__ */ jsx("div", { children: description }),
actions && /* @__PURE__ */ jsx("div", { className: "mt-14", children: actions })
]
}
);
}
export {
SectionHelper as S,
useResumeSubscription as a,
useCancelSubscription as u
};
//# sourceMappingURL=section-helper-708a2a0a.mjs.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,102 @@
import { jsxs, jsx } from "react/jsx-runtime";
import SwaggerUI from "swagger-ui-react";
import { useMemo } from "react";
import { u as useSettings, N as Navbar, b1 as Footer } from "../server-entry.mjs";
import "react-dom/server";
import "process";
import "http";
import "@tanstack/react-query";
import "axios";
import "react-router-dom/server.mjs";
import "framer-motion";
import "slugify";
import "deepmerge";
import "clsx";
import "@internationalized/date";
import "nano-memoize";
import "zustand";
import "zustand/middleware/immer";
import "nanoid";
import "@react-aria/utils";
import "@react-aria/focus";
import "@floating-ui/react-dom";
import "react-merge-refs";
import "react-dom";
import "react-router-dom";
import "@internationalized/number";
import "react-hook-form";
import "dot-object";
import "@react-stately/utils";
import "@react-aria/ssr";
import "immer";
import "axios-retry";
import "tus-js-client";
import "react-use-cookie";
import "mime-match";
import "react-use-clipboard";
const swaggerUi = "";
function SwaggerApiDocsPage() {
const settings = useSettings();
const plugins = useMemo(() => {
return getPluginsConfig(settings);
}, [settings]);
return /* @__PURE__ */ jsxs("div", { className: "h-full overflow-y-auto bg-alt", children: [
/* @__PURE__ */ jsx(Navbar, { size: "sm" }),
/* @__PURE__ */ jsxs("div", { className: "container mx-auto", children: [
/* @__PURE__ */ jsx(
SwaggerUI,
{
url: `${settings.base_url}/swagger.yaml`,
plugins,
onComplete: (system) => {
var _a;
const hash = location.hash.slice(1);
if (hash) {
const el = document.querySelector(
`#operations-${hash.replace(/\//g, "-")}`
);
if (el) {
el.scrollIntoView();
(_a = el.querySelector("button")) == null ? void 0 : _a.click();
}
}
}
}
),
/* @__PURE__ */ jsx(Footer, { className: "px-20" })
] })
] });
}
function getPluginsConfig(settings) {
return [
{
statePlugins: {
spec: {
wrapActions: {
updateSpec: (oriAction) => {
return (spec) => {
spec = spec.replaceAll(
"SITE_NAME",
settings.branding.site_name.replace(":", "")
);
spec = spec.replaceAll("SITE_URL", settings.base_url);
return oriAction(spec);
};
},
// Add current server url to docs
updateJsonSpec: (oriAction) => {
return (spec) => {
spec.servers = [{ url: `${settings.base_url}/api/v1` }];
return oriAction(spec);
};
}
}
}
}
}
];
}
export {
SwaggerApiDocsPage as default
};
//# sourceMappingURL=swagger-api-docs-page-6fa913ed.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"swagger-api-docs-page-6fa913ed.mjs","sources":["../../../common/resources/client/swagger/swagger-api-docs-page.tsx"],"sourcesContent":["import SwaggerUI from 'swagger-ui-react';\nimport 'swagger-ui-react/swagger-ui.css';\nimport {Settings} from '../core/settings/settings';\nimport {useMemo} from 'react';\nimport {Navbar} from '../ui/navigation/navbar/navbar';\nimport {Footer} from '../ui/footer/footer';\nimport {useSettings} from '../core/settings/use-settings';\n\nexport default function SwaggerApiDocsPage() {\n const settings = useSettings();\n\n const plugins = useMemo(() => {\n return getPluginsConfig(settings);\n }, [settings]);\n\n return (\n <div className=\"h-full overflow-y-auto bg-alt\">\n <Navbar size=\"sm\" />\n <div className=\"container mx-auto\">\n <SwaggerUI\n url={`${settings.base_url}/swagger.yaml`}\n plugins={plugins}\n onComplete={system => {\n //scroll to Tickets/incomingEmail\n const hash = location.hash.slice(1);\n if (hash) {\n const el = document.querySelector(\n `#operations-${hash.replace(/\\//g, '-')}`,\n );\n if (el) {\n el.scrollIntoView();\n el.querySelector('button')?.click();\n }\n }\n }}\n />\n <Footer className=\"px-20\" />\n </div>\n </div>\n );\n}\n\nfunction getPluginsConfig(settings: Settings) {\n return [\n {\n statePlugins: {\n spec: {\n wrapActions: {\n updateSpec: (oriAction: any) => {\n return (spec: any) => {\n // Replace site name\n spec = spec.replaceAll(\n 'SITE_NAME',\n settings.branding.site_name.replace(':', ''),\n );\n // Replace site url\n spec = spec.replaceAll('SITE_URL', settings.base_url);\n return oriAction(spec);\n };\n },\n // Add current server url to docs\n updateJsonSpec: (oriAction: any) => {\n return (spec: any) => {\n spec.servers = [{url: `${settings.base_url}/api/v1`}];\n return oriAction(spec);\n };\n },\n },\n },\n },\n },\n ];\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAwB,qBAAqB;AAC3C,QAAM,WAAW;AAEX,QAAA,UAAU,QAAQ,MAAM;AAC5B,WAAO,iBAAiB,QAAQ;AAAA,EAAA,GAC/B,CAAC,QAAQ,CAAC;AAGX,SAAA,qBAAC,OAAI,EAAA,WAAU,iCACb,UAAA;AAAA,IAAC,oBAAA,QAAA,EAAO,MAAK,KAAK,CAAA;AAAA,IAClB,qBAAC,OAAI,EAAA,WAAU,qBACb,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK,GAAG,SAAS,QAAQ;AAAA,UACzB;AAAA,UACA,YAAY,CAAU,WAAA;;AAEpB,kBAAM,OAAO,SAAS,KAAK,MAAM,CAAC;AAClC,gBAAI,MAAM;AACR,oBAAM,KAAK,SAAS;AAAA,gBAClB,eAAe,KAAK,QAAQ,OAAO,GAAG,CAAC;AAAA,cAAA;AAEzC,kBAAI,IAAI;AACN,mBAAG,eAAe;AACf,yBAAA,cAAc,QAAQ,MAAtB,mBAAyB;AAAA,cAC9B;AAAA,YACF;AAAA,UACF;AAAA,QAAA;AAAA,MACF;AAAA,MACA,oBAAC,QAAO,EAAA,WAAU,QAAQ,CAAA;AAAA,IAAA,GAC5B;AAAA,EACF,EAAA,CAAA;AAEJ;AAEA,SAAS,iBAAiB,UAAoB;AACrC,SAAA;AAAA,IACL;AAAA,MACE,cAAc;AAAA,QACZ,MAAM;AAAA,UACJ,aAAa;AAAA,YACX,YAAY,CAAC,cAAmB;AAC9B,qBAAO,CAAC,SAAc;AAEpB,uBAAO,KAAK;AAAA,kBACV;AAAA,kBACA,SAAS,SAAS,UAAU,QAAQ,KAAK,EAAE;AAAA,gBAAA;AAG7C,uBAAO,KAAK,WAAW,YAAY,SAAS,QAAQ;AACpD,uBAAO,UAAU,IAAI;AAAA,cAAA;AAAA,YAEzB;AAAA;AAAA,YAEA,gBAAgB,CAAC,cAAmB;AAClC,qBAAO,CAAC,SAAc;AACf,qBAAA,UAAU,CAAC,EAAC,KAAK,GAAG,SAAS,QAAQ,WAAU;AACpD,uBAAO,UAAU,IAAI;AAAA,cAAA;AAAA,YAEzB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EAAA;AAEJ;"}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

12724
bootstrap/ssr/server-entry.mjs Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long