@phatvu/web-component-poc 1.0.6 → 1.0.7
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/cjs/fast-button.cjs.entry.js +46 -0
- package/dist/cjs/{fast-button_4.cjs.entry.js → fast-carousel.cjs.entry.js} +1 -231
- package/dist/cjs/fast-input_4.cjs.entry.js +499 -0
- package/dist/cjs/{index-B2BTpdbN.js → index-BEvZs91D.js} +2 -2
- package/dist/cjs/job-card.cjs.entry.js +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/web-component-poc.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +3 -1
- package/dist/collection/components/fast-input/fast-input.css +55 -0
- package/dist/collection/components/fast-input/fast-input.js +335 -0
- package/dist/collection/components/jobs-list-only/jobs-list-only.js +180 -3
- package/dist/collection/components/jobs-list-reactive/jobs-list-reactive.css +8 -0
- package/dist/collection/components/jobs-list-reactive/jobs-list-reactive.js +203 -0
- package/dist/components/fast-button.js +1 -1
- package/dist/components/fast-carousel.js +1 -1
- package/dist/components/fast-input.d.ts +11 -0
- package/dist/components/fast-input.js +1 -0
- package/dist/components/index.js +1 -1
- package/dist/components/job-card.js +1 -1
- package/dist/components/jobs-item.js +1 -1
- package/dist/components/jobs-list-only.js +1 -1
- package/dist/components/jobs-list-reactive.d.ts +11 -0
- package/dist/components/jobs-list-reactive.js +1 -0
- package/dist/components/{p-ClQDwJJB.js → p-DQiaLjLf.js} +1 -1
- package/dist/esm/fast-button.entry.js +44 -0
- package/dist/esm/{fast-button_4.entry.js → fast-carousel.entry.js} +2 -229
- package/dist/esm/fast-input_4.entry.js +494 -0
- package/dist/esm/{index-Dk5CvWmb.js → index-C_ZLQIpp.js} +2 -2
- package/dist/esm/job-card.entry.js +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/web-component-poc.js +3 -3
- package/dist/types/components/fast-input/fast-input.d.ts +37 -0
- package/dist/types/components/jobs-list-only/jobs-list-only.d.ts +22 -0
- package/dist/types/components/jobs-list-reactive/jobs-list-reactive.d.ts +26 -0
- package/dist/types/components.d.ts +223 -0
- package/dist/web-component-poc/p-618fba28.entry.js +1 -0
- package/dist/web-component-poc/p-7d45772f.entry.js +1 -0
- package/dist/web-component-poc/{p-52c85341.entry.js → p-bef7c8e2.entry.js} +1 -1
- package/dist/web-component-poc/p-cfb9aed9.entry.js +1 -0
- package/dist/web-component-poc/web-component-poc.esm.js +1 -1
- package/hydrate/index.js +354 -6
- package/hydrate/index.mjs +354 -6
- package/package.json +5 -1
- package/dist/web-component-poc/p-96761988.entry.js +0 -1
- /package/dist/components/{p-UM9TUfe3.js → p-BiaJAQXY.js} +0 -0
- /package/dist/web-component-poc/{p-Dk5CvWmb.js → p-C_ZLQIpp.js} +0 -0
package/hydrate/index.js
CHANGED
|
@@ -132,7 +132,7 @@ function hydrateFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateResu
|
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
const NAMESPACE = 'web-component-poc';
|
|
135
|
-
const BUILD = /* web-component-poc */ { hotModuleReplacement: false, hydratedSelectorName: "hydrated",
|
|
135
|
+
const BUILD = /* web-component-poc */ { hotModuleReplacement: false, hydratedSelectorName: "hydrated", propChangeCallback: false, shadowDom: false, slotRelocation: true, state: true, updatable: true};
|
|
136
136
|
|
|
137
137
|
/*
|
|
138
138
|
Stencil Hydrate Platform v4.43.2 | MIT Licensed | https://stenciljs.com
|
|
@@ -4507,7 +4507,7 @@ var registerInstance = (lazyInstance, hostRef) => {
|
|
|
4507
4507
|
if (!hostRef) return void 0;
|
|
4508
4508
|
lazyInstance.__stencil__getHostRef = () => hostRef;
|
|
4509
4509
|
hostRef.$lazyInstance$ = lazyInstance;
|
|
4510
|
-
if (hostRef.$cmpMeta$.$flags$ & 512 /* hasModernPropertyDecls */ && (BUILD.
|
|
4510
|
+
if (hostRef.$cmpMeta$.$flags$ & 512 /* hasModernPropertyDecls */ && (BUILD.state)) {
|
|
4511
4511
|
reWireGetterSetter(lazyInstance, hostRef);
|
|
4512
4512
|
}
|
|
4513
4513
|
return hostRef;
|
|
@@ -6507,6 +6507,155 @@ class CustomButton {
|
|
|
6507
6507
|
}; }
|
|
6508
6508
|
}
|
|
6509
6509
|
|
|
6510
|
+
const fastInputCss = () => `.fast-input{position:relative;display:inline-flex;gap:0.5rem}.fast-input__field{flex:1;padding:0.5rem 0.75rem;font-size:1rem;border:1px solid #ccc;border-radius:4px}.fast-input__button{padding:0.5rem 1rem;font-size:1rem;cursor:pointer;background:#0070f3;color:#fff;border:none;border-radius:4px}.fast-input__dropdown{position:absolute;top:100%;left:0;right:0;margin:0;padding:0;list-style:none;background:#fff;border:1px solid #ccc;border-top:none;border-radius:0 0 4px 4px;z-index:100;max-height:200px;overflow-y:auto}.fast-input__dropdown-item{padding:0.5rem 0.75rem;cursor:pointer}.fast-input__dropdown-item:hover{background:#f0f0f0}.fast-input__dropdown-loading{padding:0.5rem 0.75rem;color:#999;font-style:italic}`;
|
|
6511
|
+
|
|
6512
|
+
class FastInput {
|
|
6513
|
+
constructor(hostRef) {
|
|
6514
|
+
registerInstance(this, hostRef);
|
|
6515
|
+
this.searchExecuted = createEvent(this, "searchExecuted");
|
|
6516
|
+
this.inputChanged = createEvent(this, "inputChanged");
|
|
6517
|
+
}
|
|
6518
|
+
placeholder = 'Search...';
|
|
6519
|
+
value = '';
|
|
6520
|
+
paramName = 'keyword';
|
|
6521
|
+
enableAutocomplete = false;
|
|
6522
|
+
autocompleteUrl = '/api/jobs/autocomplete';
|
|
6523
|
+
targetPath;
|
|
6524
|
+
debounceMs = 300;
|
|
6525
|
+
minChars = 3;
|
|
6526
|
+
searchExecuted;
|
|
6527
|
+
inputChanged;
|
|
6528
|
+
inputValue = '';
|
|
6529
|
+
suggestions = [];
|
|
6530
|
+
showDropdown = false;
|
|
6531
|
+
autocompleteLoading = false;
|
|
6532
|
+
debounceTimer;
|
|
6533
|
+
popstateHandler;
|
|
6534
|
+
connectedCallback() {
|
|
6535
|
+
const urlValue = this.getUrlParam();
|
|
6536
|
+
this.inputValue = urlValue !== null ? urlValue : this.value;
|
|
6537
|
+
this.popstateHandler = () => {
|
|
6538
|
+
this.inputValue = this.getUrlParam() ?? '';
|
|
6539
|
+
};
|
|
6540
|
+
window.addEventListener('popstate', this.popstateHandler);
|
|
6541
|
+
}
|
|
6542
|
+
disconnectedCallback() {
|
|
6543
|
+
window.removeEventListener('popstate', this.popstateHandler);
|
|
6544
|
+
clearTimeout(this.debounceTimer);
|
|
6545
|
+
}
|
|
6546
|
+
getUrlParam() {
|
|
6547
|
+
const params = new URLSearchParams(window.location.search);
|
|
6548
|
+
return params.get(this.paramName);
|
|
6549
|
+
}
|
|
6550
|
+
updateUrlParam(value) {
|
|
6551
|
+
const params = new URLSearchParams(window.location.search);
|
|
6552
|
+
if (value) {
|
|
6553
|
+
params.set(this.paramName, value);
|
|
6554
|
+
}
|
|
6555
|
+
else {
|
|
6556
|
+
params.delete(this.paramName);
|
|
6557
|
+
}
|
|
6558
|
+
const qs = params.toString();
|
|
6559
|
+
const newUrl = qs
|
|
6560
|
+
? `${window.location.pathname}?${qs}`
|
|
6561
|
+
: window.location.pathname;
|
|
6562
|
+
history.pushState({}, '', newUrl);
|
|
6563
|
+
}
|
|
6564
|
+
submit() {
|
|
6565
|
+
this.updateUrlParam(this.inputValue);
|
|
6566
|
+
document.dispatchEvent(new CustomEvent('search-executed', {
|
|
6567
|
+
detail: { keyword: this.inputValue },
|
|
6568
|
+
bubbles: true,
|
|
6569
|
+
composed: true,
|
|
6570
|
+
}));
|
|
6571
|
+
this.searchExecuted.emit({ keyword: this.inputValue });
|
|
6572
|
+
this.showDropdown = false;
|
|
6573
|
+
}
|
|
6574
|
+
handleInput = (e) => {
|
|
6575
|
+
const value = e.target.value;
|
|
6576
|
+
this.inputValue = value;
|
|
6577
|
+
this.inputChanged.emit({ value });
|
|
6578
|
+
if (this.enableAutocomplete) {
|
|
6579
|
+
this.scheduleAutocomplete(value);
|
|
6580
|
+
}
|
|
6581
|
+
};
|
|
6582
|
+
handleKeydown = (e) => {
|
|
6583
|
+
if (e.key === 'Enter') {
|
|
6584
|
+
this.submit();
|
|
6585
|
+
}
|
|
6586
|
+
else if (e.key === 'Escape') {
|
|
6587
|
+
this.showDropdown = false;
|
|
6588
|
+
}
|
|
6589
|
+
};
|
|
6590
|
+
handleBlur = () => {
|
|
6591
|
+
this.showDropdown = false;
|
|
6592
|
+
};
|
|
6593
|
+
scheduleAutocomplete(value) {
|
|
6594
|
+
clearTimeout(this.debounceTimer);
|
|
6595
|
+
if (value.length < this.minChars) {
|
|
6596
|
+
this.showDropdown = false;
|
|
6597
|
+
return;
|
|
6598
|
+
}
|
|
6599
|
+
this.debounceTimer = setTimeout(() => this.fetchSuggestions(value), this.debounceMs);
|
|
6600
|
+
}
|
|
6601
|
+
async fetchSuggestions(keyword) {
|
|
6602
|
+
if (!this.targetPath) {
|
|
6603
|
+
console.warn('[fast-input] target-path is required for autocomplete');
|
|
6604
|
+
return;
|
|
6605
|
+
}
|
|
6606
|
+
this.autocompleteLoading = true;
|
|
6607
|
+
this.showDropdown = true;
|
|
6608
|
+
try {
|
|
6609
|
+
const res = await fetch(this.autocompleteUrl, {
|
|
6610
|
+
method: 'POST',
|
|
6611
|
+
headers: { 'Content-Type': 'application/json' },
|
|
6612
|
+
body: JSON.stringify({ keyword, target_path: this.targetPath }),
|
|
6613
|
+
});
|
|
6614
|
+
if (!res.ok)
|
|
6615
|
+
throw new Error('autocomplete request failed');
|
|
6616
|
+
const data = await res.json();
|
|
6617
|
+
this.suggestions = data;
|
|
6618
|
+
}
|
|
6619
|
+
catch {
|
|
6620
|
+
this.showDropdown = false;
|
|
6621
|
+
this.suggestions = [];
|
|
6622
|
+
}
|
|
6623
|
+
finally {
|
|
6624
|
+
this.autocompleteLoading = false;
|
|
6625
|
+
}
|
|
6626
|
+
}
|
|
6627
|
+
selectSuggestion(title) {
|
|
6628
|
+
this.inputValue = title;
|
|
6629
|
+
this.showDropdown = false;
|
|
6630
|
+
this.submit();
|
|
6631
|
+
}
|
|
6632
|
+
render() {
|
|
6633
|
+
return (hAsync("div", { key: '3a9d31c7b109205600addc326d63979585f10bcd', class: "fast-input" }, hAsync("input", { key: '8f238fe9e002f367d4939616be8c06d938d76045', type: "text", class: "fast-input__field", placeholder: this.placeholder, value: this.inputValue, onInput: this.handleInput, onKeyDown: this.handleKeydown, onBlur: this.handleBlur }), hAsync("button", { key: '7b7404f13432750ece669da8ce68be15179921de', class: "fast-input__button", type: "button", onClick: () => this.submit() }, "Search"), this.enableAutocomplete && this.showDropdown && (hAsync("ul", { key: '1438bacadc21c183842a8bdaa3f336bffb152e14', class: "fast-input__dropdown" }, this.autocompleteLoading ? (hAsync("li", { class: "fast-input__dropdown-loading" }, "Loading...")) : (this.suggestions.map(s => (hAsync("li", { class: "fast-input__dropdown-item", onMouseDown: e => { e.preventDefault(); }, onClick: () => this.selectSuggestion(s.title) }, s.title))))))));
|
|
6634
|
+
}
|
|
6635
|
+
static get style() { return fastInputCss(); }
|
|
6636
|
+
static get cmpMeta() { return {
|
|
6637
|
+
"$flags$": 512,
|
|
6638
|
+
"$tagName$": "fast-input",
|
|
6639
|
+
"$members$": {
|
|
6640
|
+
"placeholder": [1],
|
|
6641
|
+
"value": [1],
|
|
6642
|
+
"paramName": [1, "param-name"],
|
|
6643
|
+
"enableAutocomplete": [4, "enable-autocomplete"],
|
|
6644
|
+
"autocompleteUrl": [1, "autocomplete-url"],
|
|
6645
|
+
"targetPath": [1, "target-path"],
|
|
6646
|
+
"debounceMs": [2, "debounce-ms"],
|
|
6647
|
+
"minChars": [2, "min-chars"],
|
|
6648
|
+
"inputValue": [32],
|
|
6649
|
+
"suggestions": [32],
|
|
6650
|
+
"showDropdown": [32],
|
|
6651
|
+
"autocompleteLoading": [32]
|
|
6652
|
+
},
|
|
6653
|
+
"$listeners$": undefined,
|
|
6654
|
+
"$lazyBundleId$": "-",
|
|
6655
|
+
"$attrsToReflect$": []
|
|
6656
|
+
}; }
|
|
6657
|
+
}
|
|
6658
|
+
|
|
6510
6659
|
const jobCardCss = () => `.job-card{display:block;padding:16px;border:1px solid #e0e0e0;border-radius:8px;background-color:#fff;box-shadow:0 2px 4px rgba(0, 0, 0, 0.08);transition:box-shadow 0.2s ease, border-color 0.2s ease}.job-card:hover{box-shadow:0 4px 8px rgba(0, 0, 0, 0.12);border-color:#d0d0d0}.job-card__header{margin-bottom:12px}.job-card__title{margin:0;font-size:18px;font-weight:700;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.job-card__title--link{text-decoration:none;color:#1f9755;transition:color 0.2s ease}.job-card__title--link:hover{text-decoration:underline;color:#1a7a43}.job-card__reference{font-size:0.875em;color:#666;background-color:#f5f5f5;padding:2px 6px;border-radius:3px}.job-card__reference--empty{display:none}.job-card__remote{background:#e8f5e9;color:#2e7d32;border-radius:100px;padding:4px 12px;text-transform:uppercase;font-size:11px;font-weight:700;line-height:1.5;white-space:nowrap}.job-card__remote--empty{display:none}.job-card__distance{display:inline-flex;align-items:center;gap:4px;margin-top:6px;font-size:13px;font-weight:500;color:#555}.job-card__distance--icon{display:inline-flex;align-items:center}.job-card__distance--icon svg{width:16px;height:16px;color:#1f9755}.job-card__content{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.job-card__info{flex:1;display:flex;flex-direction:column;gap:8px}.job-card__street,.job-card__brand,.job-card__employment-type{display:flex;align-items:center;flex-wrap:wrap;gap:4px 6px;font-size:14px}.job-card__street--empty,.job-card__brand--empty,.job-card__employment-type--empty{color:#999}.job-card__street--icon,.job-card__brand--icon,.job-card__employment-type--icon{display:inline-flex;align-items:center;flex-shrink:0}.job-card__street--icon svg,.job-card__brand--icon svg,.job-card__employment-type--icon svg{width:16px;height:16px;color:#666}.job-card__street--label,.job-card__brand--label,.job-card__employment-type--label{color:#333}.job-card__street--label__wrapper{display:flex;align-items:center;gap:6px}.job-card__street--more-locations__wrapper{display:flex;align-items:center;gap:2px;font-size:12px;margin-left:2px}.job-card__street--amount{font-weight:600;color:#1f9755}.job-card__street--more-locations{color:#999}.job-card__apply{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:10px 16px;background-color:#198754;color:#fff;border-radius:4px;text-decoration:none;font-weight:600;font-size:14px;transition:background-color 0.2s ease, transform 0.1s ease;white-space:nowrap;flex-shrink:0}.job-card__apply:hover{background-color:#1a6f47;transform:translateY(-1px)}.job-card__apply:active{transform:translateY(0)}.job-card__apply--icon{display:inline-flex;align-items:center}.job-card__apply--icon svg{width:14px;height:14px}@media (max-width: 768px){.job-card{padding:12px}.job-card__content{flex-direction:column;gap:10px}.job-card__apply{width:100%;justify-content:center}.job-card__title{font-size:16px}}@media (max-width: 480px){.job-card{padding:10px}.job-card__title{font-size:15px}.job-card__distance{font-size:12px}.job-card__street,.job-card__brand,.job-card__employment-type{font-size:13px}}`;
|
|
6511
6660
|
|
|
6512
6661
|
/**
|
|
@@ -6829,6 +6978,7 @@ const defaultNoResultsLine2 = 'Please refine your keywords in the search bar abo
|
|
|
6829
6978
|
class JobsListOnly {
|
|
6830
6979
|
constructor(hostRef) {
|
|
6831
6980
|
registerInstance(this, hostRef);
|
|
6981
|
+
this.fetchComplete = createEvent(this, "fetchComplete");
|
|
6832
6982
|
}
|
|
6833
6983
|
/**
|
|
6834
6984
|
* When "true", use built-in mock data (for local/dev/docs). Otherwise use `jobs` from API/parent.
|
|
@@ -6852,16 +7002,84 @@ class JobsListOnly {
|
|
|
6852
7002
|
enableKilometers = false;
|
|
6853
7003
|
/** Extra CSS class on the root element (avoid prop name "class" / "classname" reserved). */
|
|
6854
7004
|
rootClass = '';
|
|
7005
|
+
/** Template string for count display. Tokens: {count} = jobs on page, {total} = total from API. */
|
|
7006
|
+
showCountText = '';
|
|
6855
7007
|
showSuggestions = false;
|
|
6856
7008
|
clearResultSuggestionsTitleText = 'Suggestions';
|
|
6857
7009
|
clearResultSuggestionsLine1 = 'Try different keywords';
|
|
6858
7010
|
clearResultSuggestionsLine2 = 'Make sure everything is spelled correctly';
|
|
6859
7011
|
clearResultSuggestionsLine3 = 'Try other locations';
|
|
6860
7012
|
clearResultSuggestionsLine4 = '';
|
|
7013
|
+
/** When true, component manages its own data fetching */
|
|
7014
|
+
autoFetch = false;
|
|
7015
|
+
/** Jobs search endpoint */
|
|
7016
|
+
apiUrl = '/api/get-jobs';
|
|
7017
|
+
/** Comma-separated URL param names to watch and forward to the API */
|
|
7018
|
+
watchParams = 'keyword';
|
|
7019
|
+
fetchedJobs = [];
|
|
7020
|
+
fetchedTotal = 0;
|
|
7021
|
+
fetchLoading = false;
|
|
7022
|
+
fetchComplete;
|
|
7023
|
+
searchExecutedHandler;
|
|
7024
|
+
popstateHandler;
|
|
7025
|
+
connectedCallback() {
|
|
7026
|
+
if (this.autoFetch) {
|
|
7027
|
+
this.fetchJobs();
|
|
7028
|
+
this.searchExecutedHandler = () => this.fetchJobs();
|
|
7029
|
+
this.popstateHandler = () => this.fetchJobs();
|
|
7030
|
+
document.addEventListener('search-executed', this.searchExecutedHandler);
|
|
7031
|
+
window.addEventListener('popstate', this.popstateHandler);
|
|
7032
|
+
}
|
|
7033
|
+
}
|
|
7034
|
+
disconnectedCallback() {
|
|
7035
|
+
if (this.autoFetch) {
|
|
7036
|
+
document.removeEventListener('search-executed', this.searchExecutedHandler);
|
|
7037
|
+
window.removeEventListener('popstate', this.popstateHandler);
|
|
7038
|
+
}
|
|
7039
|
+
}
|
|
7040
|
+
async fetchJobs() {
|
|
7041
|
+
this.fetchLoading = true;
|
|
7042
|
+
const params = new URLSearchParams(window.location.search);
|
|
7043
|
+
const watchList = this.watchParams.split(',').map(p => p.trim()).filter(Boolean);
|
|
7044
|
+
const query = new URLSearchParams();
|
|
7045
|
+
for (const key of watchList) {
|
|
7046
|
+
const val = params.get(key);
|
|
7047
|
+
if (val !== null)
|
|
7048
|
+
query.set(key, val);
|
|
7049
|
+
}
|
|
7050
|
+
const url = `${this.apiUrl}?${query.toString()}`;
|
|
7051
|
+
try {
|
|
7052
|
+
const res = await fetch(url, {
|
|
7053
|
+
method: 'POST',
|
|
7054
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7055
|
+
body: JSON.stringify({ disable_switch_search_mode: false }),
|
|
7056
|
+
});
|
|
7057
|
+
if (!res.ok)
|
|
7058
|
+
throw new Error('fetch failed');
|
|
7059
|
+
const data = await res.json();
|
|
7060
|
+
this.fetchedJobs = data.jobs;
|
|
7061
|
+
this.fetchedTotal = data.totalJob;
|
|
7062
|
+
this.fetchComplete.emit({ jobs: data.jobs, totalJob: data.totalJob });
|
|
7063
|
+
}
|
|
7064
|
+
catch {
|
|
7065
|
+
// preserve stale data, just stop loading
|
|
7066
|
+
}
|
|
7067
|
+
finally {
|
|
7068
|
+
this.fetchLoading = false;
|
|
7069
|
+
}
|
|
7070
|
+
}
|
|
7071
|
+
renderCountText(count, total) {
|
|
7072
|
+
return this.showCountText
|
|
7073
|
+
.replace('{count}', String(count))
|
|
7074
|
+
.replace('{total}', String(total));
|
|
7075
|
+
}
|
|
6861
7076
|
getJobsArray() {
|
|
6862
7077
|
if (this.mockData) {
|
|
6863
7078
|
return mockJobsListOnly;
|
|
6864
7079
|
}
|
|
7080
|
+
if (this.autoFetch) {
|
|
7081
|
+
return this.fetchedJobs;
|
|
7082
|
+
}
|
|
6865
7083
|
const j = this.jobs;
|
|
6866
7084
|
if (Array.isArray(j))
|
|
6867
7085
|
return j;
|
|
@@ -6881,11 +7099,15 @@ class JobsListOnly {
|
|
|
6881
7099
|
}
|
|
6882
7100
|
render() {
|
|
6883
7101
|
const jobsArray = this.getJobsArray();
|
|
6884
|
-
const loading = this.mockData ? false : this.loading;
|
|
6885
|
-
const totalJob = this.mockData
|
|
7102
|
+
const loading = this.mockData ? false : (this.autoFetch ? this.fetchLoading : this.loading);
|
|
7103
|
+
const totalJob = this.mockData
|
|
7104
|
+
? jobsArray.length
|
|
7105
|
+
: this.autoFetch
|
|
7106
|
+
? this.fetchedTotal
|
|
7107
|
+
: (this.totalJob || jobsArray.length);
|
|
6886
7108
|
const showNoResults = !loading && totalJob === 0 && !this.showSuggestions;
|
|
6887
7109
|
const showSuggestionsBlock = !loading && totalJob === 0 && this.showSuggestions;
|
|
6888
|
-
return (hAsync("div", { key: '
|
|
7110
|
+
return (hAsync("div", { key: '1116855473d28d650641b9d962243bfcdcb434ec', class: `jobs-list-root ${this.rootClass}`.trim() }, hAsync("div", { key: 'fcef04f1da9ad4e150af9f59921688f5781d9d43', class: "results-container" }, this.autoFetch && this.fetchLoading && (hAsync("div", { key: '75b157c82c89691c7ce73d12ea0144b3b45485c3', class: "jobs-list-only__loading" }, "Loading...")), hAsync("div", { key: 'b09f9879e10ee4a93e32177611912da5f19f3526', class: loading ? 'loader' : 'loader hide', "aria-hidden": !loading }), totalJob > 0 && this.showCountText && (hAsync("p", { key: 'd10f800fb0a33d82531d5f1728bac4ceba2ed577', class: "jobs-list-only__count" }, this.renderCountText(jobsArray.length, totalJob))), totalJob > 0 && (hAsync("div", { key: '18153ed1338bd48f7be4f043b11ce15e3271f27b', class: "card" }, hAsync("ul", { key: '766e128b1fd5adb456530ae39e92ba8eb0b5d6cf', class: "results-list front" }, jobsArray.map((job, index) => this.renderJobItem(job, index))))), showNoResults && (hAsync("div", { key: 'ed6f3d2bd2bbedabd6e69d508ea1425580e6941f', class: "share-jobs__no-results" }, hAsync("h2", { key: '2302656e33340c69e84cb949afb7256b8f35f440' }, this.noResultsLine1), hAsync("h3", { key: '1c7e6642441a96c04ee26883fdec4f81b0fe6cec' }, this.noResultsLine2))), showSuggestionsBlock && (hAsync("div", { key: 'be7af85f64455918545e88952ca6ff00f0a970c5', class: "card primary-color" }, hAsync("h4", { key: '2f63deb8131190eff882308544b15f767b6f3edc', class: "result-suggestions-title" }, this.clearResultSuggestionsTitleText, ":"), hAsync("ul", { key: 'cb18daaa9e2c2c442c5b906ed370dcd653b5262d', class: "results-list front" }, hAsync("li", { key: 'ff1d5c6518b75c0daa35b43df7162b0dfecde25e', class: "result-suggestions-line" }, this.clearResultSuggestionsLine1), hAsync("li", { key: '4099fd7bf8dcf114eca28702a498ab0938f5de46', class: "result-suggestions-line" }, this.clearResultSuggestionsLine2), hAsync("li", { key: 'fb65b54c3c0b14bc58112977eb4c7c56c1246a45', class: "result-suggestions-line" }, this.clearResultSuggestionsLine3), this.clearResultSuggestionsLine4 && (hAsync("li", { key: '10f745e74cf68a2b1c42e6f49f810a8b59eb27b6', class: "result-suggestions-line" }, this.clearResultSuggestionsLine4))))))));
|
|
6889
7111
|
}
|
|
6890
7112
|
static get style() { return jobsListOnlyCss(); }
|
|
6891
7113
|
static get cmpMeta() { return {
|
|
@@ -6907,12 +7129,136 @@ class JobsListOnly {
|
|
|
6907
7129
|
"remoteLocationText": [1, "remote-location-text"],
|
|
6908
7130
|
"enableKilometers": [4, "enable-kilometers"],
|
|
6909
7131
|
"rootClass": [1, "root-class"],
|
|
7132
|
+
"showCountText": [1, "show-count-text"],
|
|
6910
7133
|
"showSuggestions": [4, "show-suggestions"],
|
|
6911
7134
|
"clearResultSuggestionsTitleText": [1, "clear-result-suggestions-title-text"],
|
|
6912
7135
|
"clearResultSuggestionsLine1": [1, "clear-result-suggestions-line-1"],
|
|
6913
7136
|
"clearResultSuggestionsLine2": [1, "clear-result-suggestions-line-2"],
|
|
6914
7137
|
"clearResultSuggestionsLine3": [1, "clear-result-suggestions-line-3"],
|
|
6915
|
-
"clearResultSuggestionsLine4": [1, "clear-result-suggestions-line-4"]
|
|
7138
|
+
"clearResultSuggestionsLine4": [1, "clear-result-suggestions-line-4"],
|
|
7139
|
+
"autoFetch": [4, "auto-fetch"],
|
|
7140
|
+
"apiUrl": [1, "api-url"],
|
|
7141
|
+
"watchParams": [1, "watch-params"],
|
|
7142
|
+
"fetchedJobs": [32],
|
|
7143
|
+
"fetchedTotal": [32],
|
|
7144
|
+
"fetchLoading": [32]
|
|
7145
|
+
},
|
|
7146
|
+
"$listeners$": undefined,
|
|
7147
|
+
"$lazyBundleId$": "-",
|
|
7148
|
+
"$attrsToReflect$": []
|
|
7149
|
+
}; }
|
|
7150
|
+
}
|
|
7151
|
+
|
|
7152
|
+
const jobsListReactiveCss = () => `jobs-list-reactive{display:block}jobs-list-reactive.loading{opacity:0.6;pointer-events:none}`;
|
|
7153
|
+
|
|
7154
|
+
class JobsListReactive {
|
|
7155
|
+
constructor(hostRef) {
|
|
7156
|
+
registerInstance(this, hostRef);
|
|
7157
|
+
this.fetchComplete = createEvent(this, "fetchComplete");
|
|
7158
|
+
}
|
|
7159
|
+
get el() { return getElement(this); }
|
|
7160
|
+
/** Jobs search endpoint */
|
|
7161
|
+
apiUrl = '/api/get-jobs';
|
|
7162
|
+
/** Comma-separated URL param names to watch and forward to the API */
|
|
7163
|
+
watchParams = 'keyword,location_name';
|
|
7164
|
+
/** CSS class added to container while fetching */
|
|
7165
|
+
loadingClass = 'loading';
|
|
7166
|
+
isLoading = false;
|
|
7167
|
+
fetchComplete;
|
|
7168
|
+
templateEl = null;
|
|
7169
|
+
searchExecutedHandler;
|
|
7170
|
+
popstateHandler;
|
|
7171
|
+
connectedCallback() {
|
|
7172
|
+
this.templateEl = this.el.querySelector('template');
|
|
7173
|
+
this.searchExecutedHandler = () => this.fetchJobs();
|
|
7174
|
+
this.popstateHandler = () => this.fetchJobs();
|
|
7175
|
+
document.addEventListener('search-executed', this.searchExecutedHandler);
|
|
7176
|
+
window.addEventListener('popstate', this.popstateHandler);
|
|
7177
|
+
}
|
|
7178
|
+
disconnectedCallback() {
|
|
7179
|
+
document.removeEventListener('search-executed', this.searchExecutedHandler);
|
|
7180
|
+
window.removeEventListener('popstate', this.popstateHandler);
|
|
7181
|
+
}
|
|
7182
|
+
buildQueryString() {
|
|
7183
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
7184
|
+
const watchList = this.watchParams.split(',').map(p => p.trim()).filter(Boolean);
|
|
7185
|
+
const query = new URLSearchParams();
|
|
7186
|
+
for (const key of watchList) {
|
|
7187
|
+
const val = urlParams.get(key);
|
|
7188
|
+
if (val !== null && val !== '') {
|
|
7189
|
+
query.set(key, val);
|
|
7190
|
+
}
|
|
7191
|
+
}
|
|
7192
|
+
return query.toString();
|
|
7193
|
+
}
|
|
7194
|
+
async fetchJobs() {
|
|
7195
|
+
this.isLoading = true;
|
|
7196
|
+
this.el.classList.add(this.loadingClass);
|
|
7197
|
+
const queryString = this.buildQueryString();
|
|
7198
|
+
const url = queryString ? `${this.apiUrl}?${queryString}` : this.apiUrl;
|
|
7199
|
+
try {
|
|
7200
|
+
const res = await fetch(url, {
|
|
7201
|
+
method: 'POST',
|
|
7202
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7203
|
+
body: JSON.stringify({ disable_switch_search_mode: false }),
|
|
7204
|
+
});
|
|
7205
|
+
if (!res.ok)
|
|
7206
|
+
throw new Error('fetch failed');
|
|
7207
|
+
const data = await res.json();
|
|
7208
|
+
this.renderJobs(data.jobs);
|
|
7209
|
+
this.updateCountElements(data.jobs.length, data.totalJob);
|
|
7210
|
+
this.fetchComplete.emit({ jobs: data.jobs, totalJob: data.totalJob });
|
|
7211
|
+
}
|
|
7212
|
+
catch {
|
|
7213
|
+
// Preserve stale data on error
|
|
7214
|
+
}
|
|
7215
|
+
finally {
|
|
7216
|
+
this.isLoading = false;
|
|
7217
|
+
this.el.classList.remove(this.loadingClass);
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
renderJobs(jobs) {
|
|
7221
|
+
if (!this.templateEl)
|
|
7222
|
+
return;
|
|
7223
|
+
// Remove all children except the template
|
|
7224
|
+
const children = Array.from(this.el.children);
|
|
7225
|
+
for (const child of children) {
|
|
7226
|
+
if (child !== this.templateEl) {
|
|
7227
|
+
child.remove();
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
// Clone template and render each job
|
|
7231
|
+
for (const job of jobs) {
|
|
7232
|
+
const clone = this.templateEl.content.cloneNode(true);
|
|
7233
|
+
const jobCard = clone.querySelector('job-card');
|
|
7234
|
+
if (jobCard) {
|
|
7235
|
+
jobCard.setAttribute('job', JSON.stringify(job));
|
|
7236
|
+
}
|
|
7237
|
+
this.el.appendChild(clone);
|
|
7238
|
+
}
|
|
7239
|
+
}
|
|
7240
|
+
updateCountElements(count, total) {
|
|
7241
|
+
const countEls = document.querySelectorAll('[data-job-count]');
|
|
7242
|
+
const totalEls = document.querySelectorAll('[data-job-total]');
|
|
7243
|
+
countEls.forEach(el => {
|
|
7244
|
+
el.textContent = String(count);
|
|
7245
|
+
});
|
|
7246
|
+
totalEls.forEach(el => {
|
|
7247
|
+
el.textContent = String(total);
|
|
7248
|
+
});
|
|
7249
|
+
}
|
|
7250
|
+
render() {
|
|
7251
|
+
return hAsync("slot", { key: '30a6fe9727eb877b6aafb99072c40811df121ba6' });
|
|
7252
|
+
}
|
|
7253
|
+
static get style() { return jobsListReactiveCss(); }
|
|
7254
|
+
static get cmpMeta() { return {
|
|
7255
|
+
"$flags$": 772,
|
|
7256
|
+
"$tagName$": "jobs-list-reactive",
|
|
7257
|
+
"$members$": {
|
|
7258
|
+
"apiUrl": [1, "api-url"],
|
|
7259
|
+
"watchParams": [1, "watch-params"],
|
|
7260
|
+
"loadingClass": [1, "loading-class"],
|
|
7261
|
+
"isLoading": [32]
|
|
6916
7262
|
},
|
|
6917
7263
|
"$listeners$": undefined,
|
|
6918
7264
|
"$lazyBundleId$": "-",
|
|
@@ -6923,9 +7269,11 @@ class JobsListOnly {
|
|
|
6923
7269
|
registerComponents([
|
|
6924
7270
|
AppCarousel,
|
|
6925
7271
|
CustomButton,
|
|
7272
|
+
FastInput,
|
|
6926
7273
|
JobCard,
|
|
6927
7274
|
JobsItem,
|
|
6928
7275
|
JobsListOnly,
|
|
7276
|
+
JobsListReactive,
|
|
6929
7277
|
]);
|
|
6930
7278
|
|
|
6931
7279
|
exports.hydrateApp = hydrateApp;
|