@caseparts-org/casecore 0.0.3 → 0.0.5
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/README.md +60 -60
- package/dist/environment.d.ts +3 -0
- package/dist/environment.js +2 -0
- package/dist/src/App.d.ts +3 -0
- package/dist/src/App.js +46 -0
- package/dist/src/lib/authentication/AuthContext.d.ts +34 -0
- package/dist/src/lib/authentication/AuthContext.js +252 -0
- package/dist/src/lib/authentication/AuthContext.test.js +214 -0
- package/dist/src/lib/authentication/AuthTypes.d.ts +82 -0
- package/dist/src/lib/authentication/AuthTypes.js +1 -0
- package/dist/src/lib/hooks/useLocalStorage.d.ts +14 -0
- package/dist/src/lib/hooks/useLocalStorage.js +41 -0
- package/dist/src/lib/hooks/useMicroFlex.d.ts +28 -0
- package/dist/src/lib/hooks/useMicroFlex.js +138 -0
- package/dist/src/lib/index.d.ts +6 -0
- package/dist/src/lib/index.js +6 -0
- package/dist/src/lib/utils/ClaimsUtils.d.ts +16 -0
- package/dist/src/lib/utils/ClaimsUtils.js +76 -0
- package/dist/src/lib/utils/SessionUtils.d.ts +7 -0
- package/dist/src/lib/utils/SessionUtils.js +18 -0
- package/dist/src/local/impersonate/Impersonate.d.ts +1 -0
- package/dist/src/local/impersonate/Impersonate.js +62 -0
- package/dist/src/local/layout/Layout.d.ts +4 -0
- package/dist/src/local/layout/Layout.js +33 -0
- package/dist/src/local/login/Login.d.ts +1 -0
- package/dist/src/local/login/Login.js +53 -0
- package/dist/src/local/microflex/MicroFlex.d.ts +1 -0
- package/dist/src/local/microflex/MicroFlex.js +47 -0
- package/dist/src/local/util/AppSettings.d.ts +109 -0
- package/dist/src/local/util/AppSettings.js +138 -0
- package/dist/src/main.d.ts +1 -0
- package/dist/src/main.js +6 -0
- package/package.json +54 -53
- package/dist/authentication/AuthContext.d.ts +0 -14
- package/dist/authentication/AuthContext.helpers.d.ts +0 -0
- package/dist/authentication/AuthContext.helpers.js +0 -1
- package/dist/authentication/AuthContext.js +0 -21
- package/dist/authentication/AuthContext.test.js +0 -29
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -1
- /package/dist/{authentication → src/lib/authentication}/AuthContext.test.d.ts +0 -0
- /package/dist/{test → src/lib/test}/setup.d.ts +0 -0
- /package/dist/{test → src/lib/test}/setup.js +0 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useState } from 'react';
|
3
|
+
import Layout from '../layout/Layout';
|
4
|
+
import { useAuthContext } from '../../lib/authentication/AuthContext';
|
5
|
+
import AppSettings from '../util/AppSettings';
|
6
|
+
export default function Impersonate() {
|
7
|
+
const { fetch, impersonate } = useAuthContext() || {};
|
8
|
+
const [search, setSearch] = useState('');
|
9
|
+
const [results, setResults] = useState([]);
|
10
|
+
const [loading, setLoading] = useState(false);
|
11
|
+
const [error, setError] = useState(null);
|
12
|
+
const handleSearch = async () => {
|
13
|
+
if (!fetch || !search)
|
14
|
+
return;
|
15
|
+
setLoading(true);
|
16
|
+
setError(null);
|
17
|
+
try {
|
18
|
+
const url = AppSettings.Authentication.ImpersonateSearch + encodeURIComponent(search);
|
19
|
+
const res = await fetch(url);
|
20
|
+
if (!res)
|
21
|
+
throw new Error('No response');
|
22
|
+
const data = await res.json();
|
23
|
+
setResults(Array.isArray(data) ? data : (data.results || []));
|
24
|
+
}
|
25
|
+
catch (e) {
|
26
|
+
setError(e.message || 'Search failed');
|
27
|
+
setResults([]);
|
28
|
+
}
|
29
|
+
finally {
|
30
|
+
setLoading(false);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
const handleKeyDown = (e) => {
|
34
|
+
if (e.key === 'Enter')
|
35
|
+
handleSearch();
|
36
|
+
};
|
37
|
+
const handleSelect = async (email) => {
|
38
|
+
if (!impersonate)
|
39
|
+
return;
|
40
|
+
try {
|
41
|
+
await impersonate(email);
|
42
|
+
// Optionally, redirect or show a message
|
43
|
+
}
|
44
|
+
catch {
|
45
|
+
setError('Impersonation failed');
|
46
|
+
}
|
47
|
+
};
|
48
|
+
return (_jsx(Layout, { children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100vh' }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 24 }, children: [_jsx("h1", { style: { margin: 0, marginRight: 24, marginBottom: 12 }, children: "Impersonate" }), _jsxs("div", { children: [_jsx("input", { type: "text", placeholder: "Search user by email or name", value: search, onChange: e => setSearch(e.target.value), onKeyDown: handleKeyDown, style: { minWidth: 300, marginRight: 8, height: '30px', paddingLeft: '4px' }, autoComplete: "impersonate-email" }), _jsx("button", { onClick: handleSearch, disabled: loading, children: "Search" })] })] }), error && _jsx("div", { style: { color: 'red', marginTop: 8 }, children: error }), _jsx("div", { style: { marginTop: 16, flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 16 }, children: results.map((user, idx) => (_jsxs("div", { style: {
|
49
|
+
border: '1px solid #ccc',
|
50
|
+
borderRadius: 8,
|
51
|
+
padding: 16,
|
52
|
+
minWidth: 260,
|
53
|
+
marginBottom: 8,
|
54
|
+
boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
|
55
|
+
cursor: 'pointer',
|
56
|
+
background: '#111',
|
57
|
+
transition: 'box-shadow 0.2s',
|
58
|
+
userSelect: 'none',
|
59
|
+
height: 'min-content'
|
60
|
+
}, onClick: () => handleSelect(user.UserName), tabIndex: 0, onKeyDown: e => { if (e.key === 'Enter')
|
61
|
+
handleSelect(user.UserName); }, children: [_jsx("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 2 }, children: user.CustId }), _jsx("div", { style: { marginBottom: 2 }, children: user.UserName }), _jsx("div", { style: { color: '#777', fontSize: 14 }, children: user.CustName })] }, user.Id || user.email || idx))) })] }) }));
|
62
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
2
|
+
import { Link } from 'react-router-dom';
|
3
|
+
import { useAuthContext } from '../../lib';
|
4
|
+
export default function Layout({ children }) {
|
5
|
+
return (_jsxs("div", { style: {
|
6
|
+
minHeight: '100vh',
|
7
|
+
width: '100vw',
|
8
|
+
display: 'flex',
|
9
|
+
flexDirection: 'column',
|
10
|
+
}, children: [_jsx(Navigation, {}), _jsx("main", { style: {
|
11
|
+
flex: 1,
|
12
|
+
display: 'flex',
|
13
|
+
alignItems: 'center',
|
14
|
+
justifyContent: 'center',
|
15
|
+
width: '100%',
|
16
|
+
}, children: children })] }));
|
17
|
+
}
|
18
|
+
export function Navigation() {
|
19
|
+
const auth = useAuthContext();
|
20
|
+
return (_jsx("nav", { style: {
|
21
|
+
width: '100%',
|
22
|
+
background: '#222',
|
23
|
+
color: '#fff',
|
24
|
+
padding: '0.5rem 1rem',
|
25
|
+
marginBottom: '2rem',
|
26
|
+
boxSizing: 'border-box',
|
27
|
+
}, children: _jsxs("ul", { style: {
|
28
|
+
display: 'flex',
|
29
|
+
listStyle: 'none',
|
30
|
+
margin: 0,
|
31
|
+
padding: 0,
|
32
|
+
}, children: [_jsx("li", { style: { marginRight: '1.5rem' }, children: _jsx(Link, { to: "/", style: { color: '#fff', textDecoration: 'none' }, children: "Home" }) }), _jsx("li", { style: { marginRight: '1.5rem' }, children: _jsx(Link, { to: "/login", style: { color: '#fff', textDecoration: 'none' }, children: auth?.email ? _jsx(_Fragment, { children: auth.email }) : _jsx(_Fragment, { children: "Login" }) }) }), _jsx("li", { style: { marginRight: '1.5rem' }, children: _jsx(Link, { to: "/impersonate", style: { color: '#fff', textDecoration: 'none' }, children: "Impersonate" }) }), _jsx("li", { style: { marginRight: '1.5rem' }, children: _jsx(Link, { to: "/microflex", style: { color: '#fff', textDecoration: 'none' }, children: "MicroFlex" }) })] }) }));
|
33
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function Login(): import("react/jsx-runtime").JSX.Element;
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useState } from 'react';
|
3
|
+
import { useAuthContext } from '../../lib/authentication/AuthContext';
|
4
|
+
import Layout from '../layout/Layout';
|
5
|
+
export default function Login() {
|
6
|
+
const auth = useAuthContext();
|
7
|
+
console.log(auth);
|
8
|
+
if (!auth || auth.userType === "Guest") {
|
9
|
+
return _jsx(LoginForm, {});
|
10
|
+
}
|
11
|
+
const userName = auth.claims?.Customer?.FirstName && auth.claims?.Customer?.LastName
|
12
|
+
? `${auth.claims.Customer.FirstName} ${auth.claims.Customer.LastName}`
|
13
|
+
: auth.claims?.Employee?.NickName || auth.claims?.Employee?.UserName || "";
|
14
|
+
return (_jsx(Layout, { children: _jsxs("div", { style: {
|
15
|
+
minWidth: 320,
|
16
|
+
maxWidth: 600,
|
17
|
+
width: '100%',
|
18
|
+
background: '#181818',
|
19
|
+
color: '#fff',
|
20
|
+
padding: 24,
|
21
|
+
borderRadius: 8,
|
22
|
+
boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
|
23
|
+
overflow: 'auto',
|
24
|
+
// maxHeight: 500,
|
25
|
+
}, children: [_jsx("h1", { style: { marginBottom: 12 }, children: "Account" }), _jsxs("div", { style: { marginBottom: 12 }, children: [_jsx("strong", { children: "Email:" }), " ", auth.email] }), _jsxs("div", { style: { marginBottom: 12 }, children: [_jsx("strong", { children: "Name:" }), " ", userName] }), _jsxs("div", { style: { marginBottom: 12 }, children: [_jsx("strong", { children: "Claims:" }), _jsx("pre", { style: {
|
26
|
+
background: '#222',
|
27
|
+
color: '#fff',
|
28
|
+
padding: 12,
|
29
|
+
borderRadius: 4,
|
30
|
+
maxHeight: 300,
|
31
|
+
overflow: 'auto',
|
32
|
+
fontSize: 13,
|
33
|
+
}, children: JSON.stringify(auth.claims, null, 2) })] }), _jsxs("div", { style: { width: '100%', display: 'flex', flexDirection: 'row', gap: 8, justifyContent: 'center' }, children: [_jsx("button", { onClick: () => auth.logout(), children: "Logout" }), auth.userType === "Employee" && auth.claims?.Customer &&
|
34
|
+
_jsx("button", { onClick: () => auth.impersonate(null), children: "Cancel Impersonation" })] })] }) }));
|
35
|
+
}
|
36
|
+
function LoginForm() {
|
37
|
+
const auth = useAuthContext();
|
38
|
+
const [email, setEmail] = useState('');
|
39
|
+
const [password, setPassword] = useState('');
|
40
|
+
const [error, setError] = useState(null);
|
41
|
+
const handleSubmit = async (e) => {
|
42
|
+
e.preventDefault();
|
43
|
+
setError(null);
|
44
|
+
try {
|
45
|
+
await auth?.login(email, password);
|
46
|
+
// Optionally redirect or show success
|
47
|
+
}
|
48
|
+
catch (err) {
|
49
|
+
setError(err?.message || 'Login failed');
|
50
|
+
}
|
51
|
+
};
|
52
|
+
return (_jsx(Layout, { children: _jsxs("div", { style: { minWidth: 300 }, children: [_jsx("h1", { children: "Login" }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx("div", { style: { marginBottom: 12 }, children: _jsxs("label", { children: ["Email:", _jsx("input", { type: "email", value: email, onChange: e => setEmail(e.target.value), required: true, style: { width: '100%', height: '30px', paddingLeft: '4px' } })] }) }), _jsx("div", { style: { marginBottom: 12 }, children: _jsxs("label", { children: ["Password:", _jsx("input", { type: "password", value: password, onChange: e => setPassword(e.target.value), required: true, style: { width: '100%', height: '30px', paddingLeft: '4px' } })] }) }), error && _jsx("div", { style: { color: 'red', marginBottom: 12 }, children: error }), _jsx("button", { type: "submit", style: { width: '100%' }, children: "Login" })] })] }) }));
|
53
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function MicroFlex(): import("react/jsx-runtime").JSX.Element;
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useState } from "react";
|
3
|
+
import useMicroFlex from "../../lib/hooks/useMicroFlex";
|
4
|
+
import AppSettings from "../util/AppSettings";
|
5
|
+
import { useAuthContext } from "../../lib";
|
6
|
+
import Layout from "../layout/Layout";
|
7
|
+
export default function MicroFlex() {
|
8
|
+
let port = '';
|
9
|
+
if (window.location.hostname.includes("localhost"))
|
10
|
+
port = window.location.port;
|
11
|
+
const auth = useAuthContext();
|
12
|
+
const apiURL = AppSettings.Endpoints.MicroFlexFormAuth(port);
|
13
|
+
// Ensure fetchFn is always defined and returns Promise<Response>
|
14
|
+
const fetchFn = (auth?.fetch ??
|
15
|
+
(async (_url, _options) => {
|
16
|
+
// fallback: throw error if fetch is not available
|
17
|
+
throw new Error("fetchFn is not defined");
|
18
|
+
}));
|
19
|
+
const { validate, cardToken, cardError, setupError, autoCompleteData, } = useMicroFlex({ initializeForm: !!auth?.initialized, apiURL, fetchFn });
|
20
|
+
const [validationResult, setValidationResult] = useState(undefined);
|
21
|
+
const [validationError, setValidationError] = useState(undefined);
|
22
|
+
const handleValidate = async () => {
|
23
|
+
setValidationResult(undefined);
|
24
|
+
setValidationError(undefined);
|
25
|
+
try {
|
26
|
+
const token = await validate();
|
27
|
+
setValidationResult(token);
|
28
|
+
}
|
29
|
+
catch (err) {
|
30
|
+
setValidationError(err?.message || String(err));
|
31
|
+
}
|
32
|
+
};
|
33
|
+
return (_jsx(Layout, { children: _jsxs("div", { style: { width: 400, maxWidth: 400 }, children: [_jsx("h2", { children: "MicroFlex Manual Test UI" }), _jsxs("div", { children: [_jsx("div", { id: "number", style: { height: 30, marginBottom: 12, borderRadius: 8, border: "1px solid #ccc", padding: 4 } }), _jsx("div", { id: "securityCode", style: { height: 30, marginBottom: 12, borderRadius: 8, border: "1px solid #ccc", padding: 4 } })] }), _jsx("button", { onClick: handleValidate, style: { marginBottom: 16 }, children: "Validate Card" }), _jsxs("div", { style: { marginBottom: 16 }, children: [validationResult && (_jsxs("div", { style: { color: "green", wordBreak: "break-all", whiteSpace: "pre-wrap", maxHeight: 200, overflow: "auto" }, children: ["Token: ", validationResult] })), validationError && (_jsxs("div", { style: { color: "red", wordBreak: "break-all", whiteSpace: "pre-wrap", maxHeight: 200, overflow: "auto" }, children: ["Validation Error: ", validationError] }))] }), _jsxs("div", { children: [_jsx("strong", { children: "Hook State:" }), _jsx("pre", { style: {
|
34
|
+
background: '#222',
|
35
|
+
color: '#fff',
|
36
|
+
padding: 12,
|
37
|
+
borderRadius: 4,
|
38
|
+
maxHeight: 300,
|
39
|
+
overflow: 'auto',
|
40
|
+
fontSize: 13,
|
41
|
+
}, children: JSON.stringify({
|
42
|
+
cardToken,
|
43
|
+
cardError,
|
44
|
+
setupError,
|
45
|
+
autoCompleteData,
|
46
|
+
}, null, 2) })] })] }) }));
|
47
|
+
}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
interface IAuthentication {
|
2
|
+
ConfirmEmail: string;
|
3
|
+
ResendConfirmationEmail: string;
|
4
|
+
ForgotPassword: string;
|
5
|
+
ResetPassword: string;
|
6
|
+
Login: string;
|
7
|
+
Logout: string;
|
8
|
+
Register: string;
|
9
|
+
ImpersonateSearch: string;
|
10
|
+
Impersonate: (_email?: string | null) => string;
|
11
|
+
ForgotPasswordUrl: string;
|
12
|
+
}
|
13
|
+
interface ICatalog {
|
14
|
+
Sections: () => string;
|
15
|
+
Blocks: (_section: string) => string;
|
16
|
+
Parts: (_block: string) => string;
|
17
|
+
Part: (_item: string, _block: string) => string;
|
18
|
+
Search: (_input: string, _count?: number, _showAll?: boolean) => string;
|
19
|
+
SearchCount: (_input: string) => string;
|
20
|
+
Images: (_name?: string) => string;
|
21
|
+
Inventory: (_partId: string) => string;
|
22
|
+
InventoryBatch: () => string;
|
23
|
+
PartPrice: (_partId: string) => string;
|
24
|
+
PartPriceBatch: () => string;
|
25
|
+
}
|
26
|
+
interface ICasePics {
|
27
|
+
PartImages: (_itemKey: string) => string;
|
28
|
+
Report: (_report: string) => string;
|
29
|
+
TopUsers: () => string;
|
30
|
+
Progress: () => string;
|
31
|
+
SaveImages: () => string;
|
32
|
+
SignalRHub: () => string;
|
33
|
+
}
|
34
|
+
interface ICheckout {
|
35
|
+
AccountInfo: (_custId: string) => string;
|
36
|
+
VerifyOrder: () => string;
|
37
|
+
GetRequestId: () => string;
|
38
|
+
SubmitOrder: () => string;
|
39
|
+
}
|
40
|
+
interface ICustomParts {
|
41
|
+
GasketProfile: (_profile: string) => string;
|
42
|
+
Heaters: () => string;
|
43
|
+
Coils: () => string;
|
44
|
+
Shelves: () => string;
|
45
|
+
}
|
46
|
+
interface IIntegrations {
|
47
|
+
CybersourceUrl: string;
|
48
|
+
Loupe: string;
|
49
|
+
}
|
50
|
+
interface IEndpoints {
|
51
|
+
Exemptions: (_custId: string) => string;
|
52
|
+
ExemptionsUrl: () => string;
|
53
|
+
Users: () => string;
|
54
|
+
Addresses: () => string;
|
55
|
+
EmployeeUsers: () => string;
|
56
|
+
Payments: () => string;
|
57
|
+
OrderDetail: (_op: string, _requestId?: string) => string;
|
58
|
+
MicroFlexFormAuth: (_port: string | null) => string;
|
59
|
+
}
|
60
|
+
interface IImages {
|
61
|
+
WebSpin: (_itemId: string) => string;
|
62
|
+
SpinStill: (_itemId: string) => string;
|
63
|
+
Supplemental: (_itemId: string) => string;
|
64
|
+
}
|
65
|
+
interface IPages {
|
66
|
+
PartFinder: string;
|
67
|
+
Intranet: string;
|
68
|
+
Account: string;
|
69
|
+
UserManager: string;
|
70
|
+
Custom: string;
|
71
|
+
Faq: string;
|
72
|
+
About: string;
|
73
|
+
Contact: string;
|
74
|
+
Forms: string;
|
75
|
+
Dashboard: string;
|
76
|
+
OrdersChart: string;
|
77
|
+
ReportClient: string;
|
78
|
+
EmployeeFaq: string;
|
79
|
+
CsrFaq: string;
|
80
|
+
ForgotPassword: string;
|
81
|
+
Register: string;
|
82
|
+
Orders: string;
|
83
|
+
Benefits: string;
|
84
|
+
CustomCoilForm: string;
|
85
|
+
CustomDoorForm: string;
|
86
|
+
CustomShelfForm: string;
|
87
|
+
}
|
88
|
+
interface IAnalytics {
|
89
|
+
GaHostname: string;
|
90
|
+
}
|
91
|
+
interface IAppSettings {
|
92
|
+
CustomerSite: string;
|
93
|
+
Version: string;
|
94
|
+
Env: string;
|
95
|
+
IsProd: boolean;
|
96
|
+
SignalR: string;
|
97
|
+
Authentication: IAuthentication;
|
98
|
+
Catalog: ICatalog;
|
99
|
+
CasePics: ICasePics;
|
100
|
+
Checkout: ICheckout;
|
101
|
+
CustomParts: ICustomParts;
|
102
|
+
Integrations: IIntegrations;
|
103
|
+
Endpoints: IEndpoints;
|
104
|
+
Images: IImages;
|
105
|
+
Pages: IPages;
|
106
|
+
Analytics: IAnalytics;
|
107
|
+
}
|
108
|
+
declare const AppSettings: IAppSettings;
|
109
|
+
export default AppSettings;
|
@@ -0,0 +1,138 @@
|
|
1
|
+
import environment from "../../../environment";
|
2
|
+
const Version = "3.6";
|
3
|
+
const IsProd = environment === "Prod";
|
4
|
+
const IsLocalRequestServer = false;
|
5
|
+
const IsLocalApi = false;
|
6
|
+
const CustomerSite = IsProd ? "https://www.caseparts.com" : "https://dev.caseparts.com";
|
7
|
+
const ApiServer = IsLocalApi
|
8
|
+
? "https://localhost:44340/api/"
|
9
|
+
: IsProd
|
10
|
+
? "https://my.caseparts.com/core/api/"
|
11
|
+
: "https://mydev.caseparts.com/core/api/";
|
12
|
+
const BaseUrl = IsLocalRequestServer
|
13
|
+
? "https://localhost:44340/"
|
14
|
+
: IsProd
|
15
|
+
? "https://my.caseparts.com/core/"
|
16
|
+
: "https://mydev.caseparts.com/core/";
|
17
|
+
const MyServer = IsLocalRequestServer
|
18
|
+
? "http://localhost:44340"
|
19
|
+
: IsProd
|
20
|
+
? "https://my.caseparts.com"
|
21
|
+
: "https://mydev.caseparts.com";
|
22
|
+
const CatalogServer = IsLocalRequestServer
|
23
|
+
? "http://localhost:44340"
|
24
|
+
: IsProd
|
25
|
+
? "https://www.caseparts.com"
|
26
|
+
: "https://dev.caseparts.com";
|
27
|
+
// const MobileServer: string = environment === "local"
|
28
|
+
// ? "http://localhost:3000"
|
29
|
+
// : IsProd
|
30
|
+
// ? "https://mobile.caseparts.com"
|
31
|
+
// : "https://mobiledev.caseparts.com";
|
32
|
+
const CatalogImageServer = IsProd ? "https://www.caseparts.com/graphics" : "https://dev.caseparts.com/graphics";
|
33
|
+
const Api = (endpoint) => ApiServer + endpoint;
|
34
|
+
const SignalR = (hub) => BaseUrl + hub;
|
35
|
+
const My = (url) => MyServer + url;
|
36
|
+
const Main = (url) => CatalogServer + url;
|
37
|
+
const AppSettings = {
|
38
|
+
CustomerSite: CustomerSite,
|
39
|
+
Version: Version,
|
40
|
+
Env: environment,
|
41
|
+
IsProd: IsProd,
|
42
|
+
SignalR: SignalR("signalr/"),
|
43
|
+
Authentication: {
|
44
|
+
ConfirmEmail: Api("authenticate/confirmemail/"),
|
45
|
+
ResendConfirmationEmail: Api("authenticate/resendconfirmemail"),
|
46
|
+
ForgotPassword: Api("authenticate/forgotpassword"),
|
47
|
+
ResetPassword: Api("authenticate/resetpassword"),
|
48
|
+
Login: Api("authenticate/login"),
|
49
|
+
Logout: Api("authenticate/logout"),
|
50
|
+
Register: Api("authenticate/register"),
|
51
|
+
ImpersonateSearch: Api("myaccount/search?val="),
|
52
|
+
Impersonate: (_email) => _email ? Api("authenticate/impersonate?email=") + _email : Api("authenticate/impersonate"),
|
53
|
+
ForgotPasswordUrl: My("/account/forgotpassword"),
|
54
|
+
},
|
55
|
+
Catalog: {
|
56
|
+
Sections: () => Api("mobilecatalog/sections"),
|
57
|
+
Blocks: (_section) => Api(`mobilecatalog/blocks/${_section}`),
|
58
|
+
Parts: (_block) => Api(`mobilecatalog/block/${_block}/parts`),
|
59
|
+
Part: (_item, _block) => Api(`mobilecatalog/parts/${_item}/${_block}`),
|
60
|
+
Search: (_input, _count = 20, _showAll = false) => Api(`mobilecatalog/search/?keywords=${_input}&rowCount=${_count}&showAll=${_showAll}`),
|
61
|
+
SearchCount: (_input) => Api(`mobilecatalog/searchCount/?keywords=${_input}`),
|
62
|
+
Images: (_name) => `${CatalogImageServer}/${_name ?? ''}`,
|
63
|
+
Inventory: (_partId) => Api(`part/inventory/${_partId}`),
|
64
|
+
InventoryBatch: () => Api(`part/inventory/batch`),
|
65
|
+
PartPrice: (_partId) => Api(`part/pricing/${_partId}`),
|
66
|
+
PartPriceBatch: () => Api(`part/pricing`),
|
67
|
+
},
|
68
|
+
CasePics: {
|
69
|
+
PartImages: (_itemKey) => Api(`casepics/part/${_itemKey}`),
|
70
|
+
Report: (_report) => Api(`casepics/report/${_report}`),
|
71
|
+
TopUsers: () => Api("casepics/top-users"),
|
72
|
+
Progress: () => Api("casepics/progress"),
|
73
|
+
SaveImages: () => Api("casepics/save"),
|
74
|
+
SignalRHub: () => SignalR("casepicshub"),
|
75
|
+
},
|
76
|
+
Checkout: {
|
77
|
+
AccountInfo: (_custId) => Api(`checkout/GetCheckoutInfo?customerid=${_custId}`),
|
78
|
+
VerifyOrder: () => Api("checkout/VerifyOrder"),
|
79
|
+
GetRequestId: () => Api("requests"),
|
80
|
+
SubmitOrder: () => Api("checkout/CreateQuote"),
|
81
|
+
},
|
82
|
+
CustomParts: {
|
83
|
+
GasketProfile: (_profile) => `${CatalogImageServer}%2fDrawings%5c${_profile}.png`,
|
84
|
+
Heaters: () => Api("part/heaters"),
|
85
|
+
Coils: () => Api("mobilecatalog/block/evaporator-coils-index/parts"),
|
86
|
+
Shelves: () => Api("mobilecatalog/block/wire-shelf-index/parts"),
|
87
|
+
},
|
88
|
+
Integrations: {
|
89
|
+
CybersourceUrl: Api("cybersource"),
|
90
|
+
Loupe: `${MyServer}/core`,
|
91
|
+
},
|
92
|
+
Endpoints: {
|
93
|
+
Exemptions: (_custId) => Api(`avatax/customers/${_custId}/exemptions`),
|
94
|
+
ExemptionsUrl: () => Api("avatax/certexpress"),
|
95
|
+
Users: () => Api("myaccount/users"),
|
96
|
+
Addresses: () => Api("myaccount/addresses"),
|
97
|
+
EmployeeUsers: () => Api("myaccount/internal/users"),
|
98
|
+
Payments: () => Api("myaccount/cards"),
|
99
|
+
OrderDetail: (_op, _requestId) => {
|
100
|
+
let url = Api(`myaccount/order/view/${_op}`);
|
101
|
+
url += _requestId ? `/${_requestId}` : "";
|
102
|
+
return url;
|
103
|
+
},
|
104
|
+
MicroFlexFormAuth: (_port) => Api(`cybersource/publickey/${_port || ''}`)
|
105
|
+
},
|
106
|
+
Images: {
|
107
|
+
WebSpin: (_itemId) => `${CatalogServer}/Ortery/360/Optimized/${_itemId}_/`,
|
108
|
+
SpinStill: (_itemId) => `${CatalogServer}/Ortery/360/Optimized/${_itemId}_/`,
|
109
|
+
Supplemental: (_itemId) => `${CatalogServer}/Ortery/2D/Optimized/${_itemId}/`,
|
110
|
+
},
|
111
|
+
Pages: {
|
112
|
+
PartFinder: Main(""),
|
113
|
+
Intranet: My("/home"),
|
114
|
+
Account: Main("/account"),
|
115
|
+
UserManager: Main("/account/cpc/users"),
|
116
|
+
Custom: Main("/custom"),
|
117
|
+
Faq: Main("/faq"),
|
118
|
+
About: Main("/about"),
|
119
|
+
Contact: Main("/account/contactus"),
|
120
|
+
Forms: Main("/forms"),
|
121
|
+
Dashboard: Main("/dash"),
|
122
|
+
OrdersChart: Main("/orders"),
|
123
|
+
ReportClient: My("/reports"),
|
124
|
+
EmployeeFaq: Main("/cpc"),
|
125
|
+
CsrFaq: Main("/csr"),
|
126
|
+
ForgotPassword: Main("/account/forgotpassword"),
|
127
|
+
Register: Main("/account/register"),
|
128
|
+
Orders: Main("/account/orders"),
|
129
|
+
Benefits: Main("/account/benefits"),
|
130
|
+
CustomCoilForm: My("/pdf/Custom Coil Order Form.pdf"),
|
131
|
+
CustomDoorForm: My("/pdf/Walk-In%20Door%20Order%20Form.pdf"),
|
132
|
+
CustomShelfForm: My("/pdf/Wire%20Shelf%20Order%20Form.pdf"),
|
133
|
+
},
|
134
|
+
Analytics: {
|
135
|
+
GaHostname: "www.caseparts.com",
|
136
|
+
},
|
137
|
+
};
|
138
|
+
export default AppSettings;
|
@@ -0,0 +1 @@
|
|
1
|
+
import './index.css';
|
package/dist/src/main.js
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { StrictMode } from 'react';
|
3
|
+
import { createRoot } from 'react-dom/client';
|
4
|
+
import './index.css';
|
5
|
+
import App from './App';
|
6
|
+
createRoot(document.getElementById('root')).render(_jsx(StrictMode, { children: _jsx(App, {}) }));
|
package/package.json
CHANGED
@@ -1,53 +1,54 @@
|
|
1
|
-
{
|
2
|
-
"name": "@caseparts-org/casecore",
|
3
|
-
"private": false,
|
4
|
-
"version": "0.0.
|
5
|
-
"type": "module",
|
6
|
-
"main": "dist/index.js",
|
7
|
-
"types": "dist/index.d.ts",
|
8
|
-
"exports": {
|
9
|
-
".": {
|
10
|
-
"types": "./dist/index.d.ts",
|
11
|
-
"import": "./dist/index.js",
|
12
|
-
"require": "./dist/index.js"
|
13
|
-
}
|
14
|
-
},
|
15
|
-
"files": [
|
16
|
-
"dist"
|
17
|
-
],
|
18
|
-
"peerDependencies": {
|
19
|
-
"react": "^18.0.0"
|
20
|
-
},
|
21
|
-
"scripts": {
|
22
|
-
"dev": "vite",
|
23
|
-
"build": "tsc -p tsconfig.json",
|
24
|
-
"lint": "eslint .",
|
25
|
-
"preview": "vite preview",
|
26
|
-
"test": "vitest",
|
27
|
-
"test:ci": "vitest run"
|
28
|
-
},
|
29
|
-
"dependencies": {
|
30
|
-
"jwt-decode": "^4.0.0",
|
31
|
-
"react": "^18.0.0",
|
32
|
-
"react-dom": "^18.0.0",
|
33
|
-
"uuid": "^11.1.0"
|
34
|
-
},
|
35
|
-
"devDependencies": {
|
36
|
-
"@eslint/js": "^9.29.0",
|
37
|
-
"@testing-library/jest-dom": "^6.6.3",
|
38
|
-
"@testing-library/react": "^16.3.0",
|
39
|
-
"@types/node": "^24.0.4",
|
40
|
-
"@types/react": "^19.1.8",
|
41
|
-
"@types/react-dom": "^19.1.6",
|
42
|
-
"@vitejs/plugin-react": "^4.5.2",
|
43
|
-
"eslint": "^9.29.0",
|
44
|
-
"eslint-plugin-react-hooks": "^5.2.0",
|
45
|
-
"eslint-plugin-react-refresh": "^0.4.20",
|
46
|
-
"globals": "^16.2.0",
|
47
|
-
"jsdom": "^26.1.0",
|
48
|
-
"
|
49
|
-
"typescript
|
50
|
-
"
|
51
|
-
"
|
52
|
-
|
53
|
-
}
|
1
|
+
{
|
2
|
+
"name": "@caseparts-org/casecore",
|
3
|
+
"private": false,
|
4
|
+
"version": "0.0.5",
|
5
|
+
"type": "module",
|
6
|
+
"main": "dist/index.js",
|
7
|
+
"types": "dist/index.d.ts",
|
8
|
+
"exports": {
|
9
|
+
".": {
|
10
|
+
"types": "./dist/index.d.ts",
|
11
|
+
"import": "./dist/index.js",
|
12
|
+
"require": "./dist/index.js"
|
13
|
+
}
|
14
|
+
},
|
15
|
+
"files": [
|
16
|
+
"dist"
|
17
|
+
],
|
18
|
+
"peerDependencies": {
|
19
|
+
"react": "^18.0.0"
|
20
|
+
},
|
21
|
+
"scripts": {
|
22
|
+
"dev": "vite",
|
23
|
+
"build": "tsc -p tsconfig.json",
|
24
|
+
"lint": "eslint .",
|
25
|
+
"preview": "vite preview",
|
26
|
+
"test": "vitest",
|
27
|
+
"test:ci": "vitest run"
|
28
|
+
},
|
29
|
+
"dependencies": {
|
30
|
+
"jwt-decode": "^4.0.0",
|
31
|
+
"react": "^18.0.0",
|
32
|
+
"react-dom": "^18.0.0",
|
33
|
+
"uuid": "^11.1.0"
|
34
|
+
},
|
35
|
+
"devDependencies": {
|
36
|
+
"@eslint/js": "^9.29.0",
|
37
|
+
"@testing-library/jest-dom": "^6.6.3",
|
38
|
+
"@testing-library/react": "^16.3.0",
|
39
|
+
"@types/node": "^24.0.4",
|
40
|
+
"@types/react": "^19.1.8",
|
41
|
+
"@types/react-dom": "^19.1.6",
|
42
|
+
"@vitejs/plugin-react": "^4.5.2",
|
43
|
+
"eslint": "^9.29.0",
|
44
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
45
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
46
|
+
"globals": "^16.2.0",
|
47
|
+
"jsdom": "^26.1.0",
|
48
|
+
"react-router-dom": "^7.6.3",
|
49
|
+
"typescript": "~5.8.3",
|
50
|
+
"typescript-eslint": "^8.34.1",
|
51
|
+
"vite": "^7.0.0",
|
52
|
+
"vitest": "^3.2.4"
|
53
|
+
}
|
54
|
+
}
|
@@ -1,14 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
export interface AuthContextValue {
|
3
|
-
initialized: string;
|
4
|
-
login: (_email: string, _password: string) => void;
|
5
|
-
user: string | null;
|
6
|
-
}
|
7
|
-
export declare const AuthContext: React.Context<AuthContextValue | undefined>;
|
8
|
-
export declare const useAuthContext: () => AuthContextValue;
|
9
|
-
export interface AuthProviderProps {
|
10
|
-
children: React.ReactNode;
|
11
|
-
apiKey: string;
|
12
|
-
loginUrl: string;
|
13
|
-
}
|
14
|
-
export declare const AuthProvider: React.FC<AuthProviderProps>;
|
File without changes
|
@@ -1 +0,0 @@
|
|
1
|
-
"use strict";
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import { createContext, useContext, useState } from "react";
|
3
|
-
export const AuthContext = createContext(undefined);
|
4
|
-
export const useAuthContext = () => {
|
5
|
-
const ctx = useContext(AuthContext);
|
6
|
-
if (!ctx)
|
7
|
-
throw new Error("Must be inside AuthProvider");
|
8
|
-
return ctx;
|
9
|
-
};
|
10
|
-
export const AuthProvider = ({ children, apiKey, loginUrl, }) => {
|
11
|
-
const [initialized] = useState("OK");
|
12
|
-
const [user, setUser] = useState(null);
|
13
|
-
const login = (email, password) => {
|
14
|
-
// Use both email and password to avoid unused variable error
|
15
|
-
console.log(`Logging in with email: ${email} and password: ${password}`);
|
16
|
-
setUser(`${email}.${password}`);
|
17
|
-
};
|
18
|
-
console.log(apiKey);
|
19
|
-
console.log(loginUrl);
|
20
|
-
return (_jsx(AuthContext.Provider, { value: { initialized, login, user }, children: children }));
|
21
|
-
};
|
@@ -1,29 +0,0 @@
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import { describe, it, expect } from 'vitest';
|
3
|
-
import { render, screen } from '@testing-library/react';
|
4
|
-
import { AuthProvider, useAuthContext } from './AuthContext';
|
5
|
-
/**
|
6
|
-
* Dummy component to consume the AuthContext
|
7
|
-
*/
|
8
|
-
function ShowAuthState() {
|
9
|
-
const { initialized } = useAuthContext();
|
10
|
-
return _jsx("span", { "data-testid": "auth-state", children: initialized });
|
11
|
-
}
|
12
|
-
describe('AuthContext', () => {
|
13
|
-
it('provides initialized state to children', () => {
|
14
|
-
render(_jsx(AuthProvider, { loginUrl: '/login', apiKey: '123', children: _jsx(ShowAuthState, {}) }));
|
15
|
-
// The initial state should be "OK"
|
16
|
-
expect(screen.getByTestId('auth-state')).toHaveTextContent('OK');
|
17
|
-
});
|
18
|
-
it('throws error if used outside AuthProvider', () => {
|
19
|
-
// Expect the hook to throw if used outside the provider
|
20
|
-
// (React Testing Library can't render hooks directly; need to use a component)
|
21
|
-
// We'll use a function to capture the error:
|
22
|
-
function CallWithoutProvider() {
|
23
|
-
useAuthContext();
|
24
|
-
return null;
|
25
|
-
}
|
26
|
-
// Wrap in a function to capture the thrown error
|
27
|
-
expect(() => render(_jsx(CallWithoutProvider, {}))).toThrow(/Must be inside AuthProvider/);
|
28
|
-
});
|
29
|
-
});
|