Skip to content

Commit 606fe52

Browse files
authored
Some improvements and minor fixes (#218)
Signed-off-by: Cintia Sánchez García <[email protected]>
1 parent 3a824b6 commit 606fe52

23 files changed

+681
-780
lines changed

gitjobs-server/static/js/common/input-range.js

+50-40
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { html, createRef, ref } from "/static/vendor/js/lit-all.v3.2.1.min.js";
1+
import { html, createRef, ref, nothing } from "/static/vendor/js/lit-all.v3.2.1.min.js";
22
import { LitWrapper } from "/static/js/common/lit-wrapper.js";
33
import { triggerActionOnForm } from "/static/js/jobboard/filters.js";
44

55
export class InputRange extends LitWrapper {
66
static properties = {
7-
form: { type: String },
8-
name: { type: String },
7+
form: { type: String | undefined },
8+
name: { type: String | undefined },
99
min: { type: Number },
1010
max: { type: Number },
1111
step: { type: Number },
@@ -14,13 +14,14 @@ export class InputRange extends LitWrapper {
1414
unit: { type: String },
1515
legendsNumber: { type: Number },
1616
visibleTooltip: { type: Boolean },
17+
type: { type: String },
1718
};
1819

1920
inputRef = createRef();
2021

2122
constructor() {
2223
super();
23-
this.form = "";
24+
this.form = undefined;
2425
this.name = undefined;
2526
this.min = 0;
2627
this.max = 100;
@@ -33,6 +34,27 @@ export class InputRange extends LitWrapper {
3334
this.legendsNumber = 5;
3435
this.visibleTooltip = false;
3536
this.steps = [];
37+
this.type = "type-1";
38+
this.colors = {
39+
"type-1": {
40+
"progress-line": "var(--color-primary-500)",
41+
thumb: "accent-primary-600",
42+
"bg-color": "bg-primary-900",
43+
peak: "border-b-primary-900",
44+
},
45+
"type-2": {
46+
"progress-line": "var(--color-lime-500)",
47+
thumb: "accent-lime-600",
48+
"bg-color": "bg-lime-900",
49+
peak: "border-b-lime-900",
50+
},
51+
"type-3": {
52+
"progress-line": "var(--color-lime-300)",
53+
thumb: "accent-lime-400",
54+
"bg-color": "bg-lime-800",
55+
peak: "border-b-lime-800",
56+
},
57+
};
3658
}
3759

3860
connectedCallback() {
@@ -103,51 +125,39 @@ export class InputRange extends LitWrapper {
103125
render() {
104126
return html`
105127
<div class="relative">
106-
${this.form !== ""
107-
? html`<input
108-
${ref(this.inputRef)}
109-
form="${this.form}"
110-
name="${this.name}"
111-
type="range"
112-
@input=${this._onInputChange}
113-
@mousedown=${() => this._updateTooltipVisibility(true)}
114-
@mouseup=${this._mouseup}
115-
min="${this.min}"
116-
max="${this.max}"
117-
step="${this.step}"
118-
value="${this.value}"
119-
class="w-full h-2 bg-stone-200 rounded-lg appearance-none cursor-pointer accent-primary-300"
120-
style="background-image: linear-gradient(90deg, var(--color-primary-500) 0%, var(--color-primary-500) ${this
121-
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) ${this
122-
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) 100%);"
123-
/>`
124-
: html`<input
125-
${ref(this.inputRef)}
126-
name="${this.name}"
127-
type="range"
128-
@input=${this._onInputChange}
129-
@mousedown=${() => this._updateTooltipVisibility(true)}
130-
@mouseup=${this._mouseup}
131-
min="${this.min}"
132-
max="${this.max}"
133-
step="${this.step}"
134-
value="${this.value}"
135-
class="w-full h-2 bg-stone-200 rounded-lg appearance-none cursor-pointer accent-primary-300"
136-
style="background-image: linear-gradient(90deg, var(--color-primary-500) 0%, var(--color-primary-500) ${this
137-
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) ${this
138-
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) 100%);"
139-
/>`}
128+
<input
129+
${ref(this.inputRef)}
130+
form="${this.form || nothing}"
131+
name="${this.name}"
132+
type="range"
133+
@input=${this._onInputChange}
134+
@mousedown=${() => this._updateTooltipVisibility(true)}
135+
@mouseup=${this._mouseup}
136+
min="${this.min}"
137+
max="${this.max}"
138+
step="${this.step}"
139+
value="${this.value}"
140+
class="w-full h-2 bg-stone-200 rounded-lg appearance-none cursor-pointer ${this.colors[this.type]
141+
.thumb}"
142+
style="background-image: linear-gradient(90deg, ${this.colors[this.type][
143+
"progress-line"
144+
]} 0%, ${this.colors[this.type]["progress-line"]} ${this
145+
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) ${this
146+
.percentValue}%, rgb(231 229 228 / var(--tw-bg-opacity, 1)) 100%);"
147+
/>
140148
<div
141149
role="tooltip"
142150
class="duration-100 transition-opacity ${this.visibleTooltip
143151
? ""
144-
: "opacity-0"} absolute z-10 inline-block px-2 py-1 text-sm font-medium text-white text-center bg-primary-900 rounded-lg shadow-xs tooltip top-8 start-[8.5px] -ms-8 w-16"
152+
: "opacity-0"} absolute z-10 inline-block px-2 py-1 text-sm font-medium text-white text-center ${this
153+
.colors[this.type]["bg-color"]} rounded-lg shadow-xs tooltip top-8 start-[8.5px] -ms-8 w-16"
145154
style="left: calc(${this.percentValue}% + ${this.offset}px);"
146155
>
147156
<small>${this.prefix}</small><span>${this._prettyNumber(this.value)}</span
148157
><small>${this.unit}</small>
149158
<div
150-
class="h-0 w-0 border-x-[6px] border-x-transparent border-b-[6px] border-b-primary-900 absolute -top-1.5 start-[25px]"
159+
class="h-0 w-0 border-x-[6px] border-x-transparent border-b-[6px] ${this.colors[this.type]
160+
.peak} absolute -top-1.5 start-[calc(50%-6px)]"
151161
></div>
152162
</div>
153163
<div class="mx-[15px]">

gitjobs-server/static/js/common/multiselect.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export class MultiSelect extends LitWrapper {
3434
}
3535

3636
disconnectedCallback() {
37-
window.addEventListener("mousedown", this.handleClickOutside);
3837
super.disconnectedCallback();
38+
window.addEventListener("mousedown", this.handleClickOutside);
3939
}
4040

4141
_filterOptions() {

gitjobs-server/static/js/common/search-location.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ export class SearchLocation extends LitWrapper {
4747
}
4848

4949
disconnectedCallback() {
50-
window.removeEventListener("mousedown", this._handleClickOutside);
5150
super.disconnectedCallback();
51+
window.removeEventListener("mousedown", this._handleClickOutside);
5252
}
5353

5454
async cleanLocation() {
@@ -71,6 +71,11 @@ export class SearchLocation extends LitWrapper {
7171

7272
_handleClickOutside = (e) => {
7373
if (!this.contains(e.target)) {
74+
if (this.location_id !== "") {
75+
this.value = this._formatLocation(this.city, this.state, this.country);
76+
} else {
77+
this.value = "";
78+
}
7479
this.options = null;
7580
}
7681
};
@@ -96,6 +101,7 @@ export class SearchLocation extends LitWrapper {
96101
_onInputChange(event) {
97102
this._isLoading = true;
98103
const value = event.target.value;
104+
this.value = value;
99105
if (value.length > 2) {
100106
debounce(this._fetchData(value), 300);
101107
}

gitjobs-server/static/js/common/searchable-filter.js

+61-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export class SearchableFilter extends LitWrapper {
1515
visibleDropdown: { type: Boolean },
1616
form: { type: String },
1717
alignment: { type: String },
18+
activeIndex: { type: Number | null },
1819
};
1920

2021
constructor() {
@@ -28,17 +29,18 @@ export class SearchableFilter extends LitWrapper {
2829
this.visibleDropdown = false;
2930
this.form = "";
3031
this.alignment = "bottom";
32+
this.activeIndex = null;
3133
}
3234

3335
connectedCallback() {
3436
super.connectedCallback();
35-
window.addEventListener("mousedown", this.handleClickOutside);
37+
window.addEventListener("mousedown", this._handleClickOutside);
3638
this._getOptions();
3739
}
3840

3941
disconnectedCallback() {
40-
window.addEventListener("mousedown", this.handleClickOutside);
4142
super.disconnectedCallback();
43+
window.addEventListener("mousedown", this._handleClickOutside);
4244
}
4345

4446
async cleanSelected() {
@@ -88,12 +90,58 @@ export class SearchableFilter extends LitWrapper {
8890
this._filterOptions();
8991
}
9092

91-
handleClickOutside = (e) => {
93+
// Check if the clicked element is outside the component
94+
_handleClickOutside = (e) => {
9295
if (!this.contains(e.target)) {
93-
this.visibleDropdown = false;
96+
this._cleanEnteredValue();
9497
}
9598
};
9699

100+
_handleKeyDown(event) {
101+
console.log("key down", event.key);
102+
switch (event.key) {
103+
// Highlight the next item in the list
104+
case "ArrowDown":
105+
this._highlightItem("down");
106+
break;
107+
// Highlight the previous item in the list
108+
case "ArrowUp":
109+
this._highlightItem("up");
110+
break;
111+
// Select the highlighted item
112+
case "Enter":
113+
event.preventDefault();
114+
if (this.activeIndex && this.options) {
115+
const activeItem = this.options[this.activeIndex];
116+
if (activeItem) {
117+
const activeItem = this.options[this.activeIndex];
118+
const name = this.name === "projects" ? activeItem.name : activeItem;
119+
this._onSelect(name);
120+
}
121+
}
122+
break;
123+
default:
124+
break;
125+
}
126+
}
127+
128+
_highlightItem(direction) {
129+
if (this.options && this.options.length > 0) {
130+
if (this.activeIndex === null) {
131+
this.activeIndex = direction === "down" ? 0 : this.options.length - 1;
132+
} else {
133+
let newIndex = direction === "down" ? this.activeIndex + 1 : this.activeIndex - 1;
134+
if (newIndex >= this.options.length) {
135+
newIndex = 0;
136+
}
137+
if (newIndex < 0) {
138+
newIndex = this.options.length - 1;
139+
}
140+
this.activeIndex = newIndex;
141+
}
142+
}
143+
}
144+
97145
async _onSelect(value) {
98146
this.selected.push(value);
99147
this.enteredValue = "";
@@ -124,6 +172,7 @@ export class SearchableFilter extends LitWrapper {
124172
</div>
125173
<input
126174
type="text"
175+
@keydown="${this._handleKeyDown}"
127176
@input=${this._onInputChange}
128177
@focus=${() => (this.visibleDropdown = true)}
129178
.value="${this.enteredValue}"
@@ -148,17 +197,21 @@ export class SearchableFilter extends LitWrapper {
148197
>
149198
${this.visibleOptions.length > 0 && this.visibleDropdown
150199
? html`<ul class="text-sm text-stone-700 overflow-auto max-h-[180px]">
151-
${this.visibleOptions.map((option) => {
200+
${this.visibleOptions.map((option, index) => {
152201
const isProjectsType = this.name === "projects";
153202
const name = isProjectsType ? option.name : option;
154203
const isSelected = this.selected.includes(name);
155-
return html`<li class="group" data-index="{{ loop.index }}">
204+
return html`<li
205+
class="group ${this.activeIndex === index ? "active" : ""}"
206+
data-index="${index}"
207+
>
156208
<button
157209
type="button"
158210
@click=${() => this._onSelect(name)}
159-
class=${`${
211+
@mouseover=${() => (this.activeIndex = index)}
212+
class=${`group-[.active]:bg-stone-100 ${
160213
isSelected ? "bg-stone-100 opacity-50" : "cursor-pointer hover:bg-stone-100"
161-
} capitalize block w-full text-left px-${isProjectsType ? "3" : "4"} py-1`}
214+
} capitalize block w-full text-left ${isProjectsType ? "px-3" : "px-4"} py-1`}
162215
?disabled="${isSelected}"
163216
>
164217
${isProjectsType

gitjobs-server/static/js/dashboard/employer/jobs.js

+40
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,43 @@ export const triggerActionOnForm = (formId, action) => {
55
htmx.trigger(form, action);
66
}
77
};
8+
9+
export const checkSalaryBeforeSubmit = () => {
10+
const salaryPeriod = document.querySelector('select[name="salary_period"]');
11+
const salaryCurrency = document.querySelector('select[name="salary_currency"]');
12+
const salary = document.querySelector('input[name="salary"]');
13+
const salaryMin = document.querySelector('input[name="salary_min"]');
14+
const salaryMax = document.querySelector('input[name="salary_max"]');
15+
16+
// Remove required attributes from all salary fields
17+
salaryPeriod.removeAttribute("required");
18+
salaryCurrency.removeAttribute("required");
19+
salary.removeAttribute("required");
20+
salaryMin.removeAttribute("required");
21+
salaryMax.removeAttribute("required");
22+
23+
const selectedSalaryOption = document.querySelector('input[name="salary_kind"]:checked');
24+
// If the salary option is range, remove the salary value and set correct required attributes
25+
// for min, max, period and currency
26+
if (selectedSalaryOption.id === "range") {
27+
salary.value = "";
28+
29+
if (salaryMin.value !== "" || salaryMax.value !== "") {
30+
salaryMin.setAttribute("required", "required");
31+
salaryMax.setAttribute("required", "required");
32+
salaryPeriod.setAttribute("required", "required");
33+
salaryCurrency.setAttribute("required", "required");
34+
}
35+
// If the salary option is exact, remove the salary min and max values and set correct required attributes
36+
// for salary, period and currency
37+
} else {
38+
salaryMin.value = "";
39+
salaryMax.value = "";
40+
41+
if (salary.value !== "") {
42+
salary.setAttribute("required", "required");
43+
salaryPeriod.setAttribute("required", "required");
44+
salaryCurrency.setAttribute("required", "required");
45+
}
46+
}
47+
};

gitjobs-server/static/js/dashboard/jobseeker/certifications.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class CertificationsSection extends LitWrapper {
6262
const hasSingleCertificationEntry = this.certifications.length === 1;
6363

6464
return html`<div class="mt-10">
65-
<div class="flex w-full lg:w-4/5 xl:w-2/3">
65+
<div class="flex w-full xl:w-2/3">
6666
<div class="flex flex-col space-y-3 me-3">
6767
<div>
6868
<button

gitjobs-server/static/js/dashboard/jobseeker/education.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class EducationSection extends LitWrapper {
6161
const hasSingleEducationItem = this.education.length === 1;
6262

6363
return html`<div class="mt-10">
64-
<div class="flex w-full lg:w-4/5 xl:w-2/3">
64+
<div class="flex w-full xl:w-2/3">
6565
<div class="flex flex-col space-y-3 me-3">
6666
<div>
6767
<button

gitjobs-server/static/js/dashboard/jobseeker/experience.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class ExperienceSection extends LitWrapper {
6161
const hasSingleExperienceRecord = this.experience.length === 1;
6262

6363
return html`<div class="mt-10">
64-
<div class="flex w-full lg:w-4/5 xl:w-2/3">
64+
<div class="flex w-full xl:w-2/3">
6565
<div class="flex flex-col space-y-3 me-3">
6666
<div>
6767
<button

gitjobs-server/static/js/dashboard/jobseeker/projects.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export class ProjectsSection extends LitWrapper {
6060
const hasSingleProject = this.projects.length === 1;
6161

6262
return html`<div class="mt-10">
63-
<div class="flex w-full lg:w-4/5 xl:w-2/3">
63+
<div class="flex w-full xl:w-2/3">
6464
<div class="flex flex-col space-y-3 me-3">
6565
<div>
6666
<button

gitjobs-server/templates/dashboard/dashboard_base.html

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
<div class="w-full px-3 lg:px-5 shrink-0">
4141
{# Logout #}
4242
<a href="/log-out"
43+
hx-boost="false"
44+
target="_self"
4345
class="group btn-primary-outline-anchor inline-flex w-full items-center justify-between">
4446
<div>Log out</div>
4547
<div class="svg-icon size-4 icon-logout group-hover:bg-white"></div>

gitjobs-server/templates/dashboard/employer/home.html

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
<button hx-put="/dashboard/employer/employers/{{ employer.employer_id }}/select"
5252
hx-trigger="click"
5353
hx-target="#dashboard-content"
54+
hx-indicator="#dashboard-spinner"
5455
class="cursor-pointer w-full flex items-center px-4 py-2 text-sm/6 hover:bg-stone-100
5556
{% if is_selected -%}bg-stone-100{%- endif %}"
5657
{% if is_selected %}disabled{% endif %}>

0 commit comments

Comments
 (0)