@streamoid/settings 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +313 -29
- package/dist/index.mjs +326 -31
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -52,6 +52,10 @@ interface SettingsAuthUser {
|
|
|
52
52
|
role?: string;
|
|
53
53
|
company?: string;
|
|
54
54
|
createdAt?: number | string;
|
|
55
|
+
/** Account-level specialization. Empty string = never answered;
|
|
56
|
+
"unspecified" = explicit skip; otherwise one of the host-defined ids
|
|
57
|
+
(e.g. "design", "merchandising"). */
|
|
58
|
+
userSpecialization?: string;
|
|
55
59
|
}
|
|
56
60
|
interface SettingsAuthAdapter {
|
|
57
61
|
user: SettingsAuthUser | null;
|
|
@@ -59,6 +63,7 @@ interface SettingsAuthAdapter {
|
|
|
59
63
|
updateProfile: (patch: {
|
|
60
64
|
name?: string;
|
|
61
65
|
imageUrl?: string | null;
|
|
66
|
+
userSpecialization?: string;
|
|
62
67
|
}) => Promise<void>;
|
|
63
68
|
clearAuth: () => void;
|
|
64
69
|
logout: () => Promise<void>;
|
|
@@ -490,6 +495,20 @@ interface SettingsApiAdapter {
|
|
|
490
495
|
fetchReferrals?: () => Promise<unknown[]>;
|
|
491
496
|
}
|
|
492
497
|
interface SettingsNavigationAdapter {
|
|
498
|
+
/**
|
|
499
|
+
* Resolve a fully-qualified URL the host wants Stripe checkout to redirect
|
|
500
|
+
* back to after success / cancel. Both flows typically land on the billing
|
|
501
|
+
* tab. The package calls this for `updateSubscription` (upgrade/downgrade)
|
|
502
|
+
* and `buyCredits` (topup) checkout payloads.
|
|
503
|
+
*
|
|
504
|
+
* When omitted, the package falls back to
|
|
505
|
+
* `${window.location.origin}${window.location.pathname}` — i.e. brings the
|
|
506
|
+
* user back to the page they triggered checkout from. Hosts override when
|
|
507
|
+
* they need a different URL shape (e.g. CXO uses
|
|
508
|
+
* `/dashboard/<wsId>/billing`, Photogenix uses
|
|
509
|
+
* `/workspace/<wsId>/settings/billing`).
|
|
510
|
+
*/
|
|
511
|
+
getCheckoutReturnUrl?: (kind: "success" | "cancel") => string;
|
|
493
512
|
/** Imperative navigate to another settings tab. */
|
|
494
513
|
navigateToTab: (tab: SettingsTab) => void;
|
|
495
514
|
/** External-link navigate (e.g. for "What's new" or referral promo links). */
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,10 @@ interface SettingsAuthUser {
|
|
|
52
52
|
role?: string;
|
|
53
53
|
company?: string;
|
|
54
54
|
createdAt?: number | string;
|
|
55
|
+
/** Account-level specialization. Empty string = never answered;
|
|
56
|
+
"unspecified" = explicit skip; otherwise one of the host-defined ids
|
|
57
|
+
(e.g. "design", "merchandising"). */
|
|
58
|
+
userSpecialization?: string;
|
|
55
59
|
}
|
|
56
60
|
interface SettingsAuthAdapter {
|
|
57
61
|
user: SettingsAuthUser | null;
|
|
@@ -59,6 +63,7 @@ interface SettingsAuthAdapter {
|
|
|
59
63
|
updateProfile: (patch: {
|
|
60
64
|
name?: string;
|
|
61
65
|
imageUrl?: string | null;
|
|
66
|
+
userSpecialization?: string;
|
|
62
67
|
}) => Promise<void>;
|
|
63
68
|
clearAuth: () => void;
|
|
64
69
|
logout: () => Promise<void>;
|
|
@@ -490,6 +495,20 @@ interface SettingsApiAdapter {
|
|
|
490
495
|
fetchReferrals?: () => Promise<unknown[]>;
|
|
491
496
|
}
|
|
492
497
|
interface SettingsNavigationAdapter {
|
|
498
|
+
/**
|
|
499
|
+
* Resolve a fully-qualified URL the host wants Stripe checkout to redirect
|
|
500
|
+
* back to after success / cancel. Both flows typically land on the billing
|
|
501
|
+
* tab. The package calls this for `updateSubscription` (upgrade/downgrade)
|
|
502
|
+
* and `buyCredits` (topup) checkout payloads.
|
|
503
|
+
*
|
|
504
|
+
* When omitted, the package falls back to
|
|
505
|
+
* `${window.location.origin}${window.location.pathname}` — i.e. brings the
|
|
506
|
+
* user back to the page they triggered checkout from. Hosts override when
|
|
507
|
+
* they need a different URL shape (e.g. CXO uses
|
|
508
|
+
* `/dashboard/<wsId>/billing`, Photogenix uses
|
|
509
|
+
* `/workspace/<wsId>/settings/billing`).
|
|
510
|
+
*/
|
|
511
|
+
getCheckoutReturnUrl?: (kind: "success" | "cancel") => string;
|
|
493
512
|
/** Imperative navigate to another settings tab. */
|
|
494
513
|
navigateToTab: (tab: SettingsTab) => void;
|
|
495
514
|
/** External-link navigate (e.g. for "What's new" or referral promo links). */
|
package/dist/index.js
CHANGED
|
@@ -4546,7 +4546,7 @@ function UpdateSubscriptionModal({
|
|
|
4546
4546
|
lineHeight: "var(--line-height-line-height-xxl)",
|
|
4547
4547
|
color: "var(--alias-text---icons-primary)"
|
|
4548
4548
|
},
|
|
4549
|
-
children: currentPlanName
|
|
4549
|
+
children: currentPlanName || "Free"
|
|
4550
4550
|
}
|
|
4551
4551
|
),
|
|
4552
4552
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col items-end", children: [
|
|
@@ -5360,9 +5360,16 @@ function UsageLogsTable({
|
|
|
5360
5360
|
);
|
|
5361
5361
|
}
|
|
5362
5362
|
function BillingContent({ embedded = false } = {}) {
|
|
5363
|
-
const { auth, workspace, api, toast } = useSettingsAdapters();
|
|
5363
|
+
const { auth, workspace, api, toast, navigation } = useSettingsAdapters();
|
|
5364
5364
|
const user = auth.user;
|
|
5365
5365
|
const workspaceId = workspace.current?.id ?? null;
|
|
5366
|
+
const resolveReturnUrl = (kind) => {
|
|
5367
|
+
if (navigation.getCheckoutReturnUrl) {
|
|
5368
|
+
return navigation.getCheckoutReturnUrl(kind);
|
|
5369
|
+
}
|
|
5370
|
+
if (typeof window === "undefined") return "";
|
|
5371
|
+
return `${window.location.origin}${window.location.pathname}`;
|
|
5372
|
+
};
|
|
5366
5373
|
const [activeTab, setActiveTab] = (0, import_react8.useState)("invoice");
|
|
5367
5374
|
const [showPlans, setShowPlans] = (0, import_react8.useState)(false);
|
|
5368
5375
|
const [showExportModal, setShowExportModal] = (0, import_react8.useState)(false);
|
|
@@ -5487,8 +5494,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5487
5494
|
quantity: 1,
|
|
5488
5495
|
customerEmail: user.email,
|
|
5489
5496
|
customMetadata: { ref: "Unified dashboard" },
|
|
5490
|
-
successUrl:
|
|
5491
|
-
cancelUrl:
|
|
5497
|
+
successUrl: resolveReturnUrl("success"),
|
|
5498
|
+
cancelUrl: resolveReturnUrl("cancel"),
|
|
5492
5499
|
action: "upgrade"
|
|
5493
5500
|
};
|
|
5494
5501
|
try {
|
|
@@ -5585,8 +5592,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5585
5592
|
if (loadingBilling) return;
|
|
5586
5593
|
setShowInitialLoader(false);
|
|
5587
5594
|
}, [showInitialLoader, initialFetchTriggered, loadingBilling]);
|
|
5588
|
-
const planName = subscription?.plan?.amount != null && subscription.plan.amount > 0 ? "Pro" : "Free";
|
|
5589
|
-
const isFreePlan = subscription?.plan?.amount
|
|
5595
|
+
const planName = subscription?.plan?.name?.trim() || (subscription?.plan?.amount != null && subscription.plan.amount > 0 ? "Pro" : "Free");
|
|
5596
|
+
const isFreePlan = subscription?.plan?.amount == null || subscription.plan.amount === 0;
|
|
5590
5597
|
const planAmount = subscription?.plan?.amount != null ? `$${(subscription.plan.amount / 100).toFixed(2)} / month` : "$0";
|
|
5591
5598
|
const usedCredits = availableCredits != null && totalCredits != null ? Math.max(0, totalCredits - availableCredits) : null;
|
|
5592
5599
|
const progressPct = usedCredits != null && totalCredits != null && totalCredits > 0 ? Math.min(100, Math.round(usedCredits / totalCredits * 100)) : 0;
|
|
@@ -5683,7 +5690,6 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5683
5690
|
additionalInfo: `${credits}:${price}`
|
|
5684
5691
|
}
|
|
5685
5692
|
);
|
|
5686
|
-
const returnUrl = `${window.location.origin}/dashboard/${workspaceId}/billing`;
|
|
5687
5693
|
try {
|
|
5688
5694
|
const res = await api.buyCredits({
|
|
5689
5695
|
serviceName: DEFAULT_TOPUP_SERVICE,
|
|
@@ -5691,8 +5697,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5691
5697
|
unitAmount: price,
|
|
5692
5698
|
itemCount: 1,
|
|
5693
5699
|
currency: "usd",
|
|
5694
|
-
successUrl:
|
|
5695
|
-
cancelUrl:
|
|
5700
|
+
successUrl: resolveReturnUrl("success"),
|
|
5701
|
+
cancelUrl: resolveReturnUrl("cancel"),
|
|
5696
5702
|
metadata: { source: "self-serve" }
|
|
5697
5703
|
});
|
|
5698
5704
|
const payloadData = "data" in res && res.data ? res.data : res;
|
|
@@ -6868,11 +6874,274 @@ function SettingsNav({
|
|
|
6868
6874
|
}
|
|
6869
6875
|
);
|
|
6870
6876
|
}
|
|
6877
|
+
var SPECIALIZATION_ICON_SIZE = 20;
|
|
6878
|
+
var SPECIALIZATION_OPTIONS = [
|
|
6879
|
+
{
|
|
6880
|
+
id: "design",
|
|
6881
|
+
label: "Design",
|
|
6882
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6883
|
+
import_icons7.SiconSwatch,
|
|
6884
|
+
{
|
|
6885
|
+
style: {
|
|
6886
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6887
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6888
|
+
}
|
|
6889
|
+
}
|
|
6890
|
+
)
|
|
6891
|
+
},
|
|
6892
|
+
{
|
|
6893
|
+
id: "merchandising",
|
|
6894
|
+
label: "Merchandising",
|
|
6895
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6896
|
+
import_icons7.SiconBag,
|
|
6897
|
+
{
|
|
6898
|
+
style: {
|
|
6899
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6900
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6901
|
+
}
|
|
6902
|
+
}
|
|
6903
|
+
)
|
|
6904
|
+
},
|
|
6905
|
+
{
|
|
6906
|
+
id: "planning",
|
|
6907
|
+
label: "Planning",
|
|
6908
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6909
|
+
import_icons7.SiconInsights,
|
|
6910
|
+
{
|
|
6911
|
+
style: {
|
|
6912
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6913
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6914
|
+
}
|
|
6915
|
+
}
|
|
6916
|
+
)
|
|
6917
|
+
},
|
|
6918
|
+
{
|
|
6919
|
+
id: "marketing_brand",
|
|
6920
|
+
label: "Marketing & brand",
|
|
6921
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6922
|
+
import_icons7.SiconAdCreator,
|
|
6923
|
+
{
|
|
6924
|
+
style: {
|
|
6925
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6926
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
)
|
|
6930
|
+
},
|
|
6931
|
+
{
|
|
6932
|
+
id: "founder_operator",
|
|
6933
|
+
label: "Founder & operator",
|
|
6934
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6935
|
+
import_icons7.SiconCrown,
|
|
6936
|
+
{
|
|
6937
|
+
style: {
|
|
6938
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6939
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6940
|
+
}
|
|
6941
|
+
}
|
|
6942
|
+
)
|
|
6943
|
+
}
|
|
6944
|
+
];
|
|
6945
|
+
function SpecializationDropdown({
|
|
6946
|
+
value,
|
|
6947
|
+
onChange,
|
|
6948
|
+
disabled
|
|
6949
|
+
}) {
|
|
6950
|
+
const [open, setOpen] = (0, import_react10.useState)(false);
|
|
6951
|
+
const containerRef = (0, import_react10.useRef)(null);
|
|
6952
|
+
(0, import_react10.useEffect)(() => {
|
|
6953
|
+
if (!open) return;
|
|
6954
|
+
function handleMouseDown(e) {
|
|
6955
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
6956
|
+
setOpen(false);
|
|
6957
|
+
}
|
|
6958
|
+
}
|
|
6959
|
+
function handleKeyDown(e) {
|
|
6960
|
+
if (e.key === "Escape") setOpen(false);
|
|
6961
|
+
}
|
|
6962
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
6963
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
6964
|
+
return () => {
|
|
6965
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
6966
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
6967
|
+
};
|
|
6968
|
+
}, [open]);
|
|
6969
|
+
const selected = SPECIALIZATION_OPTIONS.find((o) => o.id === value);
|
|
6970
|
+
const labelText = selected ? selected.label : value === "unspecified" ? "Not specified" : "Select specialization";
|
|
6971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
6972
|
+
"div",
|
|
6973
|
+
{
|
|
6974
|
+
ref: containerRef,
|
|
6975
|
+
className: "flex flex-col items-start w-full",
|
|
6976
|
+
style: { gap: "var(--spacing-xs)", position: "relative" },
|
|
6977
|
+
children: [
|
|
6978
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6979
|
+
"span",
|
|
6980
|
+
{
|
|
6981
|
+
style: {
|
|
6982
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
6983
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
6984
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
6985
|
+
color: "var(--alias-text---icons-tertiary)"
|
|
6986
|
+
},
|
|
6987
|
+
children: "Specialization"
|
|
6988
|
+
}
|
|
6989
|
+
),
|
|
6990
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
6991
|
+
"button",
|
|
6992
|
+
{
|
|
6993
|
+
type: "button",
|
|
6994
|
+
onClick: () => !disabled && setOpen((v) => !v),
|
|
6995
|
+
disabled,
|
|
6996
|
+
"aria-haspopup": "listbox",
|
|
6997
|
+
"aria-expanded": open,
|
|
6998
|
+
style: {
|
|
6999
|
+
width: "100%",
|
|
7000
|
+
height: 48,
|
|
7001
|
+
display: "flex",
|
|
7002
|
+
alignItems: "center",
|
|
7003
|
+
gap: "var(--spacing-md, 8px)",
|
|
7004
|
+
padding: "var(--spacing-xl, 12px) var(--spacing-3xl, 16px)",
|
|
7005
|
+
background: "var(--alias-fill-neutral-neutral, #1a1a1a)",
|
|
7006
|
+
borderRadius: "var(--radius-3xl, 16px)",
|
|
7007
|
+
border: "none",
|
|
7008
|
+
cursor: disabled ? "default" : "pointer",
|
|
7009
|
+
opacity: disabled ? 0.5 : 1,
|
|
7010
|
+
color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)",
|
|
7011
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
7012
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
7013
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
7014
|
+
textAlign: "left"
|
|
7015
|
+
},
|
|
7016
|
+
children: [
|
|
7017
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7018
|
+
"span",
|
|
7019
|
+
{
|
|
7020
|
+
style: {
|
|
7021
|
+
display: "flex",
|
|
7022
|
+
alignItems: "center",
|
|
7023
|
+
justifyContent: "center",
|
|
7024
|
+
width: 24,
|
|
7025
|
+
height: 24,
|
|
7026
|
+
color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)"
|
|
7027
|
+
},
|
|
7028
|
+
children: selected ? selected.icon : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons7.SiconBolt, {})
|
|
7029
|
+
}
|
|
7030
|
+
),
|
|
7031
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7032
|
+
"span",
|
|
7033
|
+
{
|
|
7034
|
+
style: {
|
|
7035
|
+
flex: 1,
|
|
7036
|
+
minWidth: 0,
|
|
7037
|
+
overflow: "hidden",
|
|
7038
|
+
textOverflow: "ellipsis",
|
|
7039
|
+
whiteSpace: "nowrap"
|
|
7040
|
+
},
|
|
7041
|
+
children: labelText
|
|
7042
|
+
}
|
|
7043
|
+
),
|
|
7044
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7045
|
+
"span",
|
|
7046
|
+
{
|
|
7047
|
+
style: {
|
|
7048
|
+
display: "flex",
|
|
7049
|
+
alignItems: "center",
|
|
7050
|
+
justifyContent: "center",
|
|
7051
|
+
width: 24,
|
|
7052
|
+
height: 24,
|
|
7053
|
+
color: "var(--alias-text---icons-primary)",
|
|
7054
|
+
transform: open ? "rotate(180deg)" : "none",
|
|
7055
|
+
transition: "transform 120ms ease-out"
|
|
7056
|
+
},
|
|
7057
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons7.SiconDown, {})
|
|
7058
|
+
}
|
|
7059
|
+
)
|
|
7060
|
+
]
|
|
7061
|
+
}
|
|
7062
|
+
),
|
|
7063
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7064
|
+
"div",
|
|
7065
|
+
{
|
|
7066
|
+
role: "listbox",
|
|
7067
|
+
style: {
|
|
7068
|
+
position: "absolute",
|
|
7069
|
+
top: "calc(100% + 4px)",
|
|
7070
|
+
left: 0,
|
|
7071
|
+
right: 0,
|
|
7072
|
+
zIndex: 50,
|
|
7073
|
+
background: "var(--alias-surface-subtleraised, #1f1f1f)",
|
|
7074
|
+
border: "1px solid var(--alias-border-divider, #242424)",
|
|
7075
|
+
borderRadius: "var(--radius-3xl, 16px)",
|
|
7076
|
+
padding: "var(--spacing-md, 8px)",
|
|
7077
|
+
display: "flex",
|
|
7078
|
+
flexDirection: "column",
|
|
7079
|
+
gap: 2,
|
|
7080
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
7081
|
+
},
|
|
7082
|
+
children: SPECIALIZATION_OPTIONS.map((opt) => {
|
|
7083
|
+
const isActive = opt.id === value;
|
|
7084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
7085
|
+
"button",
|
|
7086
|
+
{
|
|
7087
|
+
type: "button",
|
|
7088
|
+
role: "option",
|
|
7089
|
+
"aria-selected": isActive,
|
|
7090
|
+
onClick: () => {
|
|
7091
|
+
onChange(opt.id);
|
|
7092
|
+
setOpen(false);
|
|
7093
|
+
},
|
|
7094
|
+
style: {
|
|
7095
|
+
display: "flex",
|
|
7096
|
+
alignItems: "center",
|
|
7097
|
+
gap: "var(--spacing-md, 8px)",
|
|
7098
|
+
padding: "var(--spacing-md, 8px) var(--spacing-3xl, 16px)",
|
|
7099
|
+
background: isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
|
|
7100
|
+
border: "none",
|
|
7101
|
+
borderRadius: "var(--radius-md, 8px)",
|
|
7102
|
+
cursor: "pointer",
|
|
7103
|
+
color: "var(--alias-text---icons-primary)",
|
|
7104
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
7105
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
7106
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
7107
|
+
textAlign: "left",
|
|
7108
|
+
height: 40
|
|
7109
|
+
},
|
|
7110
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "var(--alias-fill-neutral-neutralhover, #242424)",
|
|
7111
|
+
onMouseLeave: (e) => e.currentTarget.style.background = isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
|
|
7112
|
+
children: [
|
|
7113
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7114
|
+
"span",
|
|
7115
|
+
{
|
|
7116
|
+
style: {
|
|
7117
|
+
display: "flex",
|
|
7118
|
+
alignItems: "center",
|
|
7119
|
+
justifyContent: "center",
|
|
7120
|
+
width: 24,
|
|
7121
|
+
height: 24
|
|
7122
|
+
},
|
|
7123
|
+
children: opt.icon
|
|
7124
|
+
}
|
|
7125
|
+
),
|
|
7126
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1 }, children: opt.label })
|
|
7127
|
+
]
|
|
7128
|
+
},
|
|
7129
|
+
opt.id
|
|
7130
|
+
);
|
|
7131
|
+
})
|
|
7132
|
+
}
|
|
7133
|
+
)
|
|
7134
|
+
]
|
|
7135
|
+
}
|
|
7136
|
+
);
|
|
7137
|
+
}
|
|
6871
7138
|
function ProfileTab() {
|
|
6872
7139
|
const { auth, imageUpload, toast } = useSettingsAdapters();
|
|
6873
7140
|
const user = auth.user;
|
|
6874
7141
|
const derivedName = user?.name ?? "";
|
|
7142
|
+
const derivedSpec = user?.userSpecialization ?? "";
|
|
6875
7143
|
const [fullName, setFullName] = (0, import_react10.useState)(derivedName);
|
|
7144
|
+
const [selectedSpec, setSelectedSpec] = (0, import_react10.useState)(derivedSpec);
|
|
6876
7145
|
const [saving, setSaving] = (0, import_react10.useState)(false);
|
|
6877
7146
|
const [imageSaving, setImageSaving] = (0, import_react10.useState)(false);
|
|
6878
7147
|
const [imagePreview, setImagePreview] = (0, import_react10.useState)(
|
|
@@ -6883,15 +7152,22 @@ function ProfileTab() {
|
|
|
6883
7152
|
const profileImage = imagePreview ?? getUserProfileImage(user);
|
|
6884
7153
|
const profileInitial = profileDisplayName.charAt(0).toUpperCase();
|
|
6885
7154
|
const disableAllActions = saving || imageSaving;
|
|
7155
|
+
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
|
|
6886
7156
|
(0, import_react10.useEffect)(() => {
|
|
6887
7157
|
setFullName(derivedName);
|
|
6888
7158
|
setImagePreview(void 0);
|
|
6889
7159
|
}, [derivedName]);
|
|
7160
|
+
(0, import_react10.useEffect)(() => {
|
|
7161
|
+
setSelectedSpec(derivedSpec);
|
|
7162
|
+
}, [derivedSpec]);
|
|
6890
7163
|
const handleSave = async () => {
|
|
6891
|
-
if (disableAllActions) return;
|
|
7164
|
+
if (disableAllActions || !dirty) return;
|
|
6892
7165
|
setSaving(true);
|
|
6893
7166
|
try {
|
|
6894
|
-
|
|
7167
|
+
const patch = {};
|
|
7168
|
+
if (fullName.trim() !== derivedName) patch.name = fullName.trim();
|
|
7169
|
+
if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
|
|
7170
|
+
await auth.updateProfile(patch);
|
|
6895
7171
|
await auth.refreshProfile();
|
|
6896
7172
|
toast.success("Profile updated");
|
|
6897
7173
|
} catch (err) {
|
|
@@ -7102,27 +7378,35 @@ function ProfileTab() {
|
|
|
7102
7378
|
}
|
|
7103
7379
|
) }),
|
|
7104
7380
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-1 min-w-0", style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7105
|
-
|
|
7381
|
+
SpecializationDropdown,
|
|
7106
7382
|
{
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
value: user?.email ?? "",
|
|
7111
|
-
placeholderFilled: user?.email ?? "chris@kepler.com",
|
|
7112
|
-
tfGroup: "icon-right",
|
|
7113
|
-
tfRightIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7114
|
-
import_icons7.SiconLock,
|
|
7115
|
-
{
|
|
7116
|
-
className: "w-6 h-6",
|
|
7117
|
-
color: "var(--alias-text---icons-primary)"
|
|
7118
|
-
}
|
|
7119
|
-
),
|
|
7120
|
-
className: "sc-text-field-full-width",
|
|
7121
|
-
style: { width: "100%" },
|
|
7122
|
-
readOnly: true
|
|
7383
|
+
value: selectedSpec,
|
|
7384
|
+
onChange: setSelectedSpec,
|
|
7385
|
+
disabled: disableAllActions
|
|
7123
7386
|
}
|
|
7124
7387
|
) })
|
|
7125
7388
|
] }),
|
|
7389
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7390
|
+
import_ui8.ScTextField,
|
|
7391
|
+
{
|
|
7392
|
+
label: "Email ID",
|
|
7393
|
+
labelGroup: "label",
|
|
7394
|
+
state: "default",
|
|
7395
|
+
value: user?.email ?? "",
|
|
7396
|
+
placeholderFilled: user?.email ?? "chris@kepler.com",
|
|
7397
|
+
tfGroup: "icon-right",
|
|
7398
|
+
tfRightIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7399
|
+
import_icons7.SiconLock,
|
|
7400
|
+
{
|
|
7401
|
+
className: "w-6 h-6",
|
|
7402
|
+
color: "var(--alias-text---icons-primary)"
|
|
7403
|
+
}
|
|
7404
|
+
),
|
|
7405
|
+
className: "sc-text-field-full-width",
|
|
7406
|
+
style: { width: "100%" },
|
|
7407
|
+
readOnly: true
|
|
7408
|
+
}
|
|
7409
|
+
) }),
|
|
7126
7410
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
7127
7411
|
"div",
|
|
7128
7412
|
{
|
|
@@ -7135,7 +7419,7 @@ function ProfileTab() {
|
|
|
7135
7419
|
text: saving ? "Saving..." : "Save changes",
|
|
7136
7420
|
variant: "secondary",
|
|
7137
7421
|
size: "md",
|
|
7138
|
-
state: saving ||
|
|
7422
|
+
state: saving || !dirty ? "disabled" : "default",
|
|
7139
7423
|
onClick: handleSave
|
|
7140
7424
|
}
|
|
7141
7425
|
),
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// src/settings-content.tsx
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useState as useState9,
|
|
4
|
+
useEffect as useEffect6,
|
|
5
|
+
useRef as useRef3,
|
|
6
|
+
useCallback as useCallback5
|
|
7
|
+
} from "react";
|
|
3
8
|
import {
|
|
4
9
|
ScSidebarMenu,
|
|
5
10
|
ScVDivider,
|
|
@@ -21,7 +26,13 @@ import {
|
|
|
21
26
|
SiconSettings,
|
|
22
27
|
SiconRight as SiconRight2,
|
|
23
28
|
SiconUserAdd as SiconUserAdd2,
|
|
24
|
-
SiconLock
|
|
29
|
+
SiconLock,
|
|
30
|
+
SiconDown,
|
|
31
|
+
SiconSwatch,
|
|
32
|
+
SiconBag,
|
|
33
|
+
SiconInsights,
|
|
34
|
+
SiconAdCreator,
|
|
35
|
+
SiconCrown
|
|
25
36
|
} from "@streamoid/icons";
|
|
26
37
|
|
|
27
38
|
// src/icons/SiconKey.tsx
|
|
@@ -4554,7 +4565,7 @@ function UpdateSubscriptionModal({
|
|
|
4554
4565
|
lineHeight: "var(--line-height-line-height-xxl)",
|
|
4555
4566
|
color: "var(--alias-text---icons-primary)"
|
|
4556
4567
|
},
|
|
4557
|
-
children: currentPlanName
|
|
4568
|
+
children: currentPlanName || "Free"
|
|
4558
4569
|
}
|
|
4559
4570
|
),
|
|
4560
4571
|
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-end", children: [
|
|
@@ -5368,9 +5379,16 @@ function UsageLogsTable({
|
|
|
5368
5379
|
);
|
|
5369
5380
|
}
|
|
5370
5381
|
function BillingContent({ embedded = false } = {}) {
|
|
5371
|
-
const { auth, workspace, api, toast } = useSettingsAdapters();
|
|
5382
|
+
const { auth, workspace, api, toast, navigation } = useSettingsAdapters();
|
|
5372
5383
|
const user = auth.user;
|
|
5373
5384
|
const workspaceId = workspace.current?.id ?? null;
|
|
5385
|
+
const resolveReturnUrl = (kind) => {
|
|
5386
|
+
if (navigation.getCheckoutReturnUrl) {
|
|
5387
|
+
return navigation.getCheckoutReturnUrl(kind);
|
|
5388
|
+
}
|
|
5389
|
+
if (typeof window === "undefined") return "";
|
|
5390
|
+
return `${window.location.origin}${window.location.pathname}`;
|
|
5391
|
+
};
|
|
5374
5392
|
const [activeTab, setActiveTab] = useState7("invoice");
|
|
5375
5393
|
const [showPlans, setShowPlans] = useState7(false);
|
|
5376
5394
|
const [showExportModal, setShowExportModal] = useState7(false);
|
|
@@ -5495,8 +5513,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5495
5513
|
quantity: 1,
|
|
5496
5514
|
customerEmail: user.email,
|
|
5497
5515
|
customMetadata: { ref: "Unified dashboard" },
|
|
5498
|
-
successUrl:
|
|
5499
|
-
cancelUrl:
|
|
5516
|
+
successUrl: resolveReturnUrl("success"),
|
|
5517
|
+
cancelUrl: resolveReturnUrl("cancel"),
|
|
5500
5518
|
action: "upgrade"
|
|
5501
5519
|
};
|
|
5502
5520
|
try {
|
|
@@ -5593,8 +5611,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5593
5611
|
if (loadingBilling) return;
|
|
5594
5612
|
setShowInitialLoader(false);
|
|
5595
5613
|
}, [showInitialLoader, initialFetchTriggered, loadingBilling]);
|
|
5596
|
-
const planName = subscription?.plan?.amount != null && subscription.plan.amount > 0 ? "Pro" : "Free";
|
|
5597
|
-
const isFreePlan = subscription?.plan?.amount
|
|
5614
|
+
const planName = subscription?.plan?.name?.trim() || (subscription?.plan?.amount != null && subscription.plan.amount > 0 ? "Pro" : "Free");
|
|
5615
|
+
const isFreePlan = subscription?.plan?.amount == null || subscription.plan.amount === 0;
|
|
5598
5616
|
const planAmount = subscription?.plan?.amount != null ? `$${(subscription.plan.amount / 100).toFixed(2)} / month` : "$0";
|
|
5599
5617
|
const usedCredits = availableCredits != null && totalCredits != null ? Math.max(0, totalCredits - availableCredits) : null;
|
|
5600
5618
|
const progressPct = usedCredits != null && totalCredits != null && totalCredits > 0 ? Math.min(100, Math.round(usedCredits / totalCredits * 100)) : 0;
|
|
@@ -5691,7 +5709,6 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5691
5709
|
additionalInfo: `${credits}:${price}`
|
|
5692
5710
|
}
|
|
5693
5711
|
);
|
|
5694
|
-
const returnUrl = `${window.location.origin}/dashboard/${workspaceId}/billing`;
|
|
5695
5712
|
try {
|
|
5696
5713
|
const res = await api.buyCredits({
|
|
5697
5714
|
serviceName: DEFAULT_TOPUP_SERVICE,
|
|
@@ -5699,8 +5716,8 @@ function BillingContent({ embedded = false } = {}) {
|
|
|
5699
5716
|
unitAmount: price,
|
|
5700
5717
|
itemCount: 1,
|
|
5701
5718
|
currency: "usd",
|
|
5702
|
-
successUrl:
|
|
5703
|
-
cancelUrl:
|
|
5719
|
+
successUrl: resolveReturnUrl("success"),
|
|
5720
|
+
cancelUrl: resolveReturnUrl("cancel"),
|
|
5704
5721
|
metadata: { source: "self-serve" }
|
|
5705
5722
|
});
|
|
5706
5723
|
const payloadData = "data" in res && res.data ? res.data : res;
|
|
@@ -6882,11 +6899,274 @@ function SettingsNav({
|
|
|
6882
6899
|
}
|
|
6883
6900
|
);
|
|
6884
6901
|
}
|
|
6902
|
+
var SPECIALIZATION_ICON_SIZE = 20;
|
|
6903
|
+
var SPECIALIZATION_OPTIONS = [
|
|
6904
|
+
{
|
|
6905
|
+
id: "design",
|
|
6906
|
+
label: "Design",
|
|
6907
|
+
icon: /* @__PURE__ */ jsx13(
|
|
6908
|
+
SiconSwatch,
|
|
6909
|
+
{
|
|
6910
|
+
style: {
|
|
6911
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6912
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
)
|
|
6916
|
+
},
|
|
6917
|
+
{
|
|
6918
|
+
id: "merchandising",
|
|
6919
|
+
label: "Merchandising",
|
|
6920
|
+
icon: /* @__PURE__ */ jsx13(
|
|
6921
|
+
SiconBag,
|
|
6922
|
+
{
|
|
6923
|
+
style: {
|
|
6924
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6925
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
)
|
|
6929
|
+
},
|
|
6930
|
+
{
|
|
6931
|
+
id: "planning",
|
|
6932
|
+
label: "Planning",
|
|
6933
|
+
icon: /* @__PURE__ */ jsx13(
|
|
6934
|
+
SiconInsights,
|
|
6935
|
+
{
|
|
6936
|
+
style: {
|
|
6937
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6938
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6939
|
+
}
|
|
6940
|
+
}
|
|
6941
|
+
)
|
|
6942
|
+
},
|
|
6943
|
+
{
|
|
6944
|
+
id: "marketing_brand",
|
|
6945
|
+
label: "Marketing & brand",
|
|
6946
|
+
icon: /* @__PURE__ */ jsx13(
|
|
6947
|
+
SiconAdCreator,
|
|
6948
|
+
{
|
|
6949
|
+
style: {
|
|
6950
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6951
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6952
|
+
}
|
|
6953
|
+
}
|
|
6954
|
+
)
|
|
6955
|
+
},
|
|
6956
|
+
{
|
|
6957
|
+
id: "founder_operator",
|
|
6958
|
+
label: "Founder & operator",
|
|
6959
|
+
icon: /* @__PURE__ */ jsx13(
|
|
6960
|
+
SiconCrown,
|
|
6961
|
+
{
|
|
6962
|
+
style: {
|
|
6963
|
+
width: SPECIALIZATION_ICON_SIZE,
|
|
6964
|
+
height: SPECIALIZATION_ICON_SIZE
|
|
6965
|
+
}
|
|
6966
|
+
}
|
|
6967
|
+
)
|
|
6968
|
+
}
|
|
6969
|
+
];
|
|
6970
|
+
function SpecializationDropdown({
|
|
6971
|
+
value,
|
|
6972
|
+
onChange,
|
|
6973
|
+
disabled
|
|
6974
|
+
}) {
|
|
6975
|
+
const [open, setOpen] = useState9(false);
|
|
6976
|
+
const containerRef = useRef3(null);
|
|
6977
|
+
useEffect6(() => {
|
|
6978
|
+
if (!open) return;
|
|
6979
|
+
function handleMouseDown(e) {
|
|
6980
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
6981
|
+
setOpen(false);
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
function handleKeyDown(e) {
|
|
6985
|
+
if (e.key === "Escape") setOpen(false);
|
|
6986
|
+
}
|
|
6987
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
6988
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
6989
|
+
return () => {
|
|
6990
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
6991
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
6992
|
+
};
|
|
6993
|
+
}, [open]);
|
|
6994
|
+
const selected = SPECIALIZATION_OPTIONS.find((o) => o.id === value);
|
|
6995
|
+
const labelText = selected ? selected.label : value === "unspecified" ? "Not specified" : "Select specialization";
|
|
6996
|
+
return /* @__PURE__ */ jsxs11(
|
|
6997
|
+
"div",
|
|
6998
|
+
{
|
|
6999
|
+
ref: containerRef,
|
|
7000
|
+
className: "flex flex-col items-start w-full",
|
|
7001
|
+
style: { gap: "var(--spacing-xs)", position: "relative" },
|
|
7002
|
+
children: [
|
|
7003
|
+
/* @__PURE__ */ jsx13(
|
|
7004
|
+
"span",
|
|
7005
|
+
{
|
|
7006
|
+
style: {
|
|
7007
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
7008
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
7009
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
7010
|
+
color: "var(--alias-text---icons-tertiary)"
|
|
7011
|
+
},
|
|
7012
|
+
children: "Specialization"
|
|
7013
|
+
}
|
|
7014
|
+
),
|
|
7015
|
+
/* @__PURE__ */ jsxs11(
|
|
7016
|
+
"button",
|
|
7017
|
+
{
|
|
7018
|
+
type: "button",
|
|
7019
|
+
onClick: () => !disabled && setOpen((v) => !v),
|
|
7020
|
+
disabled,
|
|
7021
|
+
"aria-haspopup": "listbox",
|
|
7022
|
+
"aria-expanded": open,
|
|
7023
|
+
style: {
|
|
7024
|
+
width: "100%",
|
|
7025
|
+
height: 48,
|
|
7026
|
+
display: "flex",
|
|
7027
|
+
alignItems: "center",
|
|
7028
|
+
gap: "var(--spacing-md, 8px)",
|
|
7029
|
+
padding: "var(--spacing-xl, 12px) var(--spacing-3xl, 16px)",
|
|
7030
|
+
background: "var(--alias-fill-neutral-neutral, #1a1a1a)",
|
|
7031
|
+
borderRadius: "var(--radius-3xl, 16px)",
|
|
7032
|
+
border: "none",
|
|
7033
|
+
cursor: disabled ? "default" : "pointer",
|
|
7034
|
+
opacity: disabled ? 0.5 : 1,
|
|
7035
|
+
color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)",
|
|
7036
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
7037
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
7038
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
7039
|
+
textAlign: "left"
|
|
7040
|
+
},
|
|
7041
|
+
children: [
|
|
7042
|
+
/* @__PURE__ */ jsx13(
|
|
7043
|
+
"span",
|
|
7044
|
+
{
|
|
7045
|
+
style: {
|
|
7046
|
+
display: "flex",
|
|
7047
|
+
alignItems: "center",
|
|
7048
|
+
justifyContent: "center",
|
|
7049
|
+
width: 24,
|
|
7050
|
+
height: 24,
|
|
7051
|
+
color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)"
|
|
7052
|
+
},
|
|
7053
|
+
children: selected ? selected.icon : /* @__PURE__ */ jsx13(SiconBolt, {})
|
|
7054
|
+
}
|
|
7055
|
+
),
|
|
7056
|
+
/* @__PURE__ */ jsx13(
|
|
7057
|
+
"span",
|
|
7058
|
+
{
|
|
7059
|
+
style: {
|
|
7060
|
+
flex: 1,
|
|
7061
|
+
minWidth: 0,
|
|
7062
|
+
overflow: "hidden",
|
|
7063
|
+
textOverflow: "ellipsis",
|
|
7064
|
+
whiteSpace: "nowrap"
|
|
7065
|
+
},
|
|
7066
|
+
children: labelText
|
|
7067
|
+
}
|
|
7068
|
+
),
|
|
7069
|
+
/* @__PURE__ */ jsx13(
|
|
7070
|
+
"span",
|
|
7071
|
+
{
|
|
7072
|
+
style: {
|
|
7073
|
+
display: "flex",
|
|
7074
|
+
alignItems: "center",
|
|
7075
|
+
justifyContent: "center",
|
|
7076
|
+
width: 24,
|
|
7077
|
+
height: 24,
|
|
7078
|
+
color: "var(--alias-text---icons-primary)",
|
|
7079
|
+
transform: open ? "rotate(180deg)" : "none",
|
|
7080
|
+
transition: "transform 120ms ease-out"
|
|
7081
|
+
},
|
|
7082
|
+
children: /* @__PURE__ */ jsx13(SiconDown, {})
|
|
7083
|
+
}
|
|
7084
|
+
)
|
|
7085
|
+
]
|
|
7086
|
+
}
|
|
7087
|
+
),
|
|
7088
|
+
open && /* @__PURE__ */ jsx13(
|
|
7089
|
+
"div",
|
|
7090
|
+
{
|
|
7091
|
+
role: "listbox",
|
|
7092
|
+
style: {
|
|
7093
|
+
position: "absolute",
|
|
7094
|
+
top: "calc(100% + 4px)",
|
|
7095
|
+
left: 0,
|
|
7096
|
+
right: 0,
|
|
7097
|
+
zIndex: 50,
|
|
7098
|
+
background: "var(--alias-surface-subtleraised, #1f1f1f)",
|
|
7099
|
+
border: "1px solid var(--alias-border-divider, #242424)",
|
|
7100
|
+
borderRadius: "var(--radius-3xl, 16px)",
|
|
7101
|
+
padding: "var(--spacing-md, 8px)",
|
|
7102
|
+
display: "flex",
|
|
7103
|
+
flexDirection: "column",
|
|
7104
|
+
gap: 2,
|
|
7105
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
7106
|
+
},
|
|
7107
|
+
children: SPECIALIZATION_OPTIONS.map((opt) => {
|
|
7108
|
+
const isActive = opt.id === value;
|
|
7109
|
+
return /* @__PURE__ */ jsxs11(
|
|
7110
|
+
"button",
|
|
7111
|
+
{
|
|
7112
|
+
type: "button",
|
|
7113
|
+
role: "option",
|
|
7114
|
+
"aria-selected": isActive,
|
|
7115
|
+
onClick: () => {
|
|
7116
|
+
onChange(opt.id);
|
|
7117
|
+
setOpen(false);
|
|
7118
|
+
},
|
|
7119
|
+
style: {
|
|
7120
|
+
display: "flex",
|
|
7121
|
+
alignItems: "center",
|
|
7122
|
+
gap: "var(--spacing-md, 8px)",
|
|
7123
|
+
padding: "var(--spacing-md, 8px) var(--spacing-3xl, 16px)",
|
|
7124
|
+
background: isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
|
|
7125
|
+
border: "none",
|
|
7126
|
+
borderRadius: "var(--radius-md, 8px)",
|
|
7127
|
+
cursor: "pointer",
|
|
7128
|
+
color: "var(--alias-text---icons-primary)",
|
|
7129
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
7130
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
7131
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
7132
|
+
textAlign: "left",
|
|
7133
|
+
height: 40
|
|
7134
|
+
},
|
|
7135
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "var(--alias-fill-neutral-neutralhover, #242424)",
|
|
7136
|
+
onMouseLeave: (e) => e.currentTarget.style.background = isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
|
|
7137
|
+
children: [
|
|
7138
|
+
/* @__PURE__ */ jsx13(
|
|
7139
|
+
"span",
|
|
7140
|
+
{
|
|
7141
|
+
style: {
|
|
7142
|
+
display: "flex",
|
|
7143
|
+
alignItems: "center",
|
|
7144
|
+
justifyContent: "center",
|
|
7145
|
+
width: 24,
|
|
7146
|
+
height: 24
|
|
7147
|
+
},
|
|
7148
|
+
children: opt.icon
|
|
7149
|
+
}
|
|
7150
|
+
),
|
|
7151
|
+
/* @__PURE__ */ jsx13("span", { style: { flex: 1 }, children: opt.label })
|
|
7152
|
+
]
|
|
7153
|
+
},
|
|
7154
|
+
opt.id
|
|
7155
|
+
);
|
|
7156
|
+
})
|
|
7157
|
+
}
|
|
7158
|
+
)
|
|
7159
|
+
]
|
|
7160
|
+
}
|
|
7161
|
+
);
|
|
7162
|
+
}
|
|
6885
7163
|
function ProfileTab() {
|
|
6886
7164
|
const { auth, imageUpload, toast } = useSettingsAdapters();
|
|
6887
7165
|
const user = auth.user;
|
|
6888
7166
|
const derivedName = user?.name ?? "";
|
|
7167
|
+
const derivedSpec = user?.userSpecialization ?? "";
|
|
6889
7168
|
const [fullName, setFullName] = useState9(derivedName);
|
|
7169
|
+
const [selectedSpec, setSelectedSpec] = useState9(derivedSpec);
|
|
6890
7170
|
const [saving, setSaving] = useState9(false);
|
|
6891
7171
|
const [imageSaving, setImageSaving] = useState9(false);
|
|
6892
7172
|
const [imagePreview, setImagePreview] = useState9(
|
|
@@ -6897,15 +7177,22 @@ function ProfileTab() {
|
|
|
6897
7177
|
const profileImage = imagePreview ?? getUserProfileImage(user);
|
|
6898
7178
|
const profileInitial = profileDisplayName.charAt(0).toUpperCase();
|
|
6899
7179
|
const disableAllActions = saving || imageSaving;
|
|
7180
|
+
const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
|
|
6900
7181
|
useEffect6(() => {
|
|
6901
7182
|
setFullName(derivedName);
|
|
6902
7183
|
setImagePreview(void 0);
|
|
6903
7184
|
}, [derivedName]);
|
|
7185
|
+
useEffect6(() => {
|
|
7186
|
+
setSelectedSpec(derivedSpec);
|
|
7187
|
+
}, [derivedSpec]);
|
|
6904
7188
|
const handleSave = async () => {
|
|
6905
|
-
if (disableAllActions) return;
|
|
7189
|
+
if (disableAllActions || !dirty) return;
|
|
6906
7190
|
setSaving(true);
|
|
6907
7191
|
try {
|
|
6908
|
-
|
|
7192
|
+
const patch = {};
|
|
7193
|
+
if (fullName.trim() !== derivedName) patch.name = fullName.trim();
|
|
7194
|
+
if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
|
|
7195
|
+
await auth.updateProfile(patch);
|
|
6909
7196
|
await auth.refreshProfile();
|
|
6910
7197
|
toast.success("Profile updated");
|
|
6911
7198
|
} catch (err) {
|
|
@@ -7116,27 +7403,35 @@ function ProfileTab() {
|
|
|
7116
7403
|
}
|
|
7117
7404
|
) }),
|
|
7118
7405
|
/* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx13(
|
|
7119
|
-
|
|
7406
|
+
SpecializationDropdown,
|
|
7120
7407
|
{
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
value: user?.email ?? "",
|
|
7125
|
-
placeholderFilled: user?.email ?? "chris@kepler.com",
|
|
7126
|
-
tfGroup: "icon-right",
|
|
7127
|
-
tfRightIcon: /* @__PURE__ */ jsx13(
|
|
7128
|
-
SiconLock,
|
|
7129
|
-
{
|
|
7130
|
-
className: "w-6 h-6",
|
|
7131
|
-
color: "var(--alias-text---icons-primary)"
|
|
7132
|
-
}
|
|
7133
|
-
),
|
|
7134
|
-
className: "sc-text-field-full-width",
|
|
7135
|
-
style: { width: "100%" },
|
|
7136
|
-
readOnly: true
|
|
7408
|
+
value: selectedSpec,
|
|
7409
|
+
onChange: setSelectedSpec,
|
|
7410
|
+
disabled: disableAllActions
|
|
7137
7411
|
}
|
|
7138
7412
|
) })
|
|
7139
7413
|
] }),
|
|
7414
|
+
/* @__PURE__ */ jsx13("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx13(
|
|
7415
|
+
ScTextField,
|
|
7416
|
+
{
|
|
7417
|
+
label: "Email ID",
|
|
7418
|
+
labelGroup: "label",
|
|
7419
|
+
state: "default",
|
|
7420
|
+
value: user?.email ?? "",
|
|
7421
|
+
placeholderFilled: user?.email ?? "chris@kepler.com",
|
|
7422
|
+
tfGroup: "icon-right",
|
|
7423
|
+
tfRightIcon: /* @__PURE__ */ jsx13(
|
|
7424
|
+
SiconLock,
|
|
7425
|
+
{
|
|
7426
|
+
className: "w-6 h-6",
|
|
7427
|
+
color: "var(--alias-text---icons-primary)"
|
|
7428
|
+
}
|
|
7429
|
+
),
|
|
7430
|
+
className: "sc-text-field-full-width",
|
|
7431
|
+
style: { width: "100%" },
|
|
7432
|
+
readOnly: true
|
|
7433
|
+
}
|
|
7434
|
+
) }),
|
|
7140
7435
|
/* @__PURE__ */ jsxs11(
|
|
7141
7436
|
"div",
|
|
7142
7437
|
{
|
|
@@ -7149,7 +7444,7 @@ function ProfileTab() {
|
|
|
7149
7444
|
text: saving ? "Saving..." : "Save changes",
|
|
7150
7445
|
variant: "secondary",
|
|
7151
7446
|
size: "md",
|
|
7152
|
-
state: saving ||
|
|
7447
|
+
state: saving || !dirty ? "disabled" : "default",
|
|
7153
7448
|
onClick: handleSave
|
|
7154
7449
|
}
|
|
7155
7450
|
),
|