Skip to content

Commit b6e1c39

Browse files
committed
List element now has some responsive fields and dropdown of completed items
1 parent 5b28e56 commit b6e1c39

File tree

17 files changed

+983
-289
lines changed

17 files changed

+983
-289
lines changed

src/components/ListItems/CheckBox.vue

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,58 @@
11
<template>
2-
<div class="checkbox-container">
3-
<label for="checkbox-input">{{ label }}</label>
4-
<input
5-
type="checkbox"
6-
id="checkbox-input"
7-
v-model="isChecked"
8-
@change="emitCheckboxChange"
9-
@keyup.enter="toggleCheckbox"
10-
tabindex="0" />
11-
</div>
12-
</template>
13-
14-
<script>
15-
export default {
16-
name: 'CheckboxInput',
17-
props: {
18-
label: {
19-
type: String,
20-
default: 'Checkbox' // Default label text
21-
}
2+
<div class="checkbox-container">
3+
<label for="checkbox-input">{{ label }}</label>
4+
<input
5+
type="checkbox"
6+
id="checkbox-input"
7+
v-model="isChecked"
8+
@change="emitCheckboxChange"
9+
@keyup.enter="toggleCheckbox"
10+
tabindex="0" />
11+
</div>
12+
</template>
13+
14+
<script>
15+
export default {
16+
name: 'CheckboxInput',
17+
props: {
18+
label: {
19+
type: String,
20+
default: 'Checkbox' // Default label text
2221
},
23-
data() {
24-
return {
25-
isChecked: false
26-
};
22+
value: {
23+
type: Boolean,
24+
default: false // Default checked state
25+
}
26+
},
27+
data() {
28+
return {
29+
isChecked: this.value // Initialize with the prop value
30+
};
31+
},
32+
watch: {
33+
value(newValue) {
34+
this.isChecked = newValue; // Update local state when prop changes
35+
}
36+
},
37+
methods: {
38+
emitCheckboxChange() {
39+
this.$emit('checkbox-toggled', this.isChecked); // Emit the checked state to the parent
40+
this.$emit('input', this.isChecked); // Emit input event for v-model binding
2741
},
28-
methods: {
29-
emitCheckboxChange() {
30-
this.$emit('checkbox-toggled', this.isChecked); // Emit the checked state to the parent
31-
},
32-
toggleCheckbox() {
33-
// Toggle the checkbox value when Enter is pressed
34-
this.isChecked = !this.isChecked;
35-
this.emitCheckboxChange(); // Emit the change
36-
}
42+
toggleCheckbox() {
43+
// Toggle the checkbox value when Enter is pressed
44+
this.isChecked = !this.isChecked;
45+
this.emitCheckboxChange(); // Emit the change
3746
}
38-
};
39-
</script>
40-
41-
<style scoped>
42-
/* Add your styling here */
43-
</style>
44-
47+
},
48+
mounted() {
49+
this.isChecked = this.value; // Set initial state based on prop value
50+
}
51+
};
52+
</script>
53+
54+
<style scoped>
55+
.checkbox-container {
56+
background-color: red; /* Change as needed */
57+
}
58+
</style>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<template>
2+
<div class="pretty-button-container">
3+
<button
4+
class="pretty-button"
5+
@mouseenter="hoverButton"
6+
@mouseleave="resetButton"
7+
@click="toggleCheck"
8+
@keyup.enter="toggleCheck"
9+
>
10+
<span class="button-label">{{ buttonLabel }}</span>
11+
</button>
12+
</div>
13+
</template>
14+
15+
<script>
16+
export default {
17+
name: 'PrettyButton',
18+
data() {
19+
return {
20+
isChecked: false, // Keeps track of whether the button is "checked"
21+
};
22+
},
23+
computed: {
24+
buttonLabel() {
25+
// Label changes based on whether the button is checked
26+
return this.isChecked ? '' : '';
27+
}
28+
},
29+
methods: {
30+
emitButtonChange() {
31+
this.$emit('checkbox-toggled', this.isChecked); // Emit the checked state to the parent
32+
},
33+
hoverButton(event) {
34+
// Temporarily show the checkmark on hover
35+
event.target.innerHTML = '';
36+
},
37+
resetButton(event) {
38+
// Reset the button to its actual checked state after hover
39+
event.target.innerHTML = '';
40+
},
41+
toggleCheck() {
42+
// Permanently check or uncheck the button on click
43+
this.isChecked = !this.isChecked;
44+
this.emitButtonChange();
45+
}
46+
}
47+
};
48+
</script>
49+
50+
<style scoped>
51+
.pretty-button-container {
52+
display: inline-block;
53+
padding-left: 3px;
54+
margin-bottom: 2px;
55+
}
56+
57+
.pretty-button {
58+
display: inline-flex;
59+
align-items: center;
60+
justify-content: center;
61+
width: 25px;
62+
height: 25px;
63+
background-color: #ddd;
64+
border: 2px solid #2d5dc7;
65+
border-radius: 5px;
66+
cursor: pointer;
67+
user-select: none;
68+
transition: background-color 0.3s, border-color 0.3s;
69+
}
70+
71+
.pretty-button:hover {
72+
background-color: #2d5dc7;
73+
}
74+
75+
.button-label {
76+
font-size: 16px;
77+
color: white;
78+
}
79+
80+
.pretty-button:hover .button-label {
81+
color: white;
82+
}
83+
</style>
Lines changed: 189 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,206 @@
11
<template>
2-
<div class="date-input-container">
3-
<label for="date-input"></label>
4-
<input type="date" id="date-input" v-model="selectedDate" @change="emitDateChange" />
2+
<div class="date-picker">
3+
<input
4+
type="text"
5+
v-model="formattedDate"
6+
@focus="showCalendar"
7+
class="date-input"
8+
readonly
9+
/>
10+
<div v-if="isCalendarVisible" class="calendar">
11+
<div class="calendar-header">
12+
<button @click="prevMonth">&lt;</button>
13+
<span>{{ monthNames[currentMonth] }} {{ currentYear }}</span>
14+
<button @click="nextMonth">&gt;</button>
15+
</div>
16+
<div class="calendar-grid">
17+
<div class="day" v-for="(day, index) in weekDays" :key="index">{{ day }}</div>
18+
<div
19+
v-for="date in displayedDates"
20+
:key="date.dateString"
21+
class="day"
22+
:class="{ 'hover': date.isHover, 'selected': date.isSelected }"
23+
@mouseover="hoverDate(date.dateString)"
24+
@mouseleave="clearHover"
25+
@click="selectDate(date.dateString)"
26+
>
27+
{{ date.day }}
28+
</div>
29+
</div>
30+
</div>
531
</div>
632
</template>
733

834
<script>
935
export default {
36+
props: {
37+
initialDate: {
38+
type: String,
39+
default: () => new Date().toISOString().split('T')[0], // Default to today
40+
},
41+
},
1042
data() {
1143
return {
12-
selectedDate: null,
44+
isCalendarVisible: false,
45+
currentYear: new Date().getFullYear(),
46+
currentMonth: new Date().getMonth(),
47+
selectedDate: this.initialDate,
48+
hoveredDate: null,
1349
};
1450
},
51+
computed: {
52+
formattedDate() {
53+
// Display the selected date directly without modification
54+
return this.hoveredDate || this.formatDate(this.incrementDate(this.selectedDate));
55+
},
56+
monthNames() {
57+
return [
58+
'January', 'February', 'March', 'April', 'May', 'June',
59+
'July', 'August', 'September', 'October', 'November', 'December',
60+
];
61+
},
62+
weekDays() {
63+
return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
64+
},
65+
displayedDates() {
66+
const dates = [];
67+
const firstDayOfMonth = new Date(this.currentYear, this.currentMonth, 1);
68+
const lastDayOfMonth = new Date(this.currentYear, this.currentMonth + 1, 0);
69+
70+
// Fill in the days leading up to the first day of the month
71+
for (let i = 0; i < firstDayOfMonth.getDay(); i++) {
72+
dates.push({ day: '', dateString: '' });
73+
}
74+
75+
// Fill in the days of the month
76+
for (let day = 1; day <= lastDayOfMonth.getDate(); day++) {
77+
const dateString = new Date(this.currentYear, this.currentMonth, day).toISOString().split('T')[0];
78+
79+
dates.push({
80+
day,
81+
dateString,
82+
isSelected: dateString === this.selectedDate,
83+
isHover: dateString === this.hoveredDate,
84+
});
85+
}
86+
87+
return dates;
88+
},
89+
},
1590
methods: {
16-
emitDateChange() {
91+
formatDate(date) {
92+
const options = { year: 'numeric', month: 'short', day: 'numeric' };
93+
return new Date(date).toLocaleDateString(undefined, options);
94+
},
95+
showCalendar() {
96+
this.isCalendarVisible = true;
97+
},
98+
hoverDate(dateString) {
99+
this.hoveredDate = dateString; // Set the hovered date
100+
},
101+
clearHover() {
102+
this.hoveredDate = null; // Clear the hover state
103+
},
104+
selectDate(dateString) {
105+
this.selectedDate = dateString; // Set the selected date
106+
this.hoveredDate = null; // Clear hover state
107+
this.isCalendarVisible = false; // Hide calendar after selection
108+
17109
this.$emit('date-selected', this.selectedDate); // Emit the selected date to the parent
18-
}
19-
}
110+
this.$emit('update:initialDate', this.selectedDate); // Sync with the parent
111+
},
112+
prevMonth() {
113+
if (this.currentMonth === 0) {
114+
this.currentMonth = 11;
115+
this.currentYear--;
116+
} else {
117+
this.currentMonth--;
118+
}
119+
},
120+
nextMonth() {
121+
if (this.currentMonth === 11) {
122+
this.currentMonth = 0;
123+
this.currentYear++;
124+
} else {
125+
this.currentMonth++;
126+
}
127+
},
128+
incrementDate(dateString) {
129+
const date = new Date(dateString);
130+
date.setDate(date.getDate()+1); // Increment the date by 1
131+
return date.toISOString().split('T')[0]; // Return the incremented date as a string in YYYY-MM-DD format
132+
},
133+
},
134+
watch: {
135+
initialDate(newValue) {
136+
this.selectedDate = newValue;
137+
const date = new Date(newValue);
138+
this.currentYear = date.getFullYear();
139+
this.currentMonth = date.getMonth();
140+
},
141+
},
142+
mounted() {
143+
this.selectedDate = this.initialDate; // Set the initial selected date
144+
},
20145
};
21146
</script>
22147

23148
<style scoped>
24-
/* Add your styling here */
149+
.date-picker {
150+
position: relative;
151+
}
152+
153+
.date-input {
154+
background-color: #1e1e1e;
155+
color: #cfcfcf;
156+
border: 1px solid #4a4a4a;
157+
border-radius: 4px;
158+
padding: 8px;
159+
width: 90%;
160+
cursor: text;
161+
}
162+
163+
.calendar {
164+
position: absolute;
165+
top: 40px;
166+
left: -10%;
167+
width: 90%;
168+
max-width: 300px;
169+
background-color: #2b2b2b;
170+
border: 1px solid #4a4a4a;
171+
border-radius: 4px;
172+
padding-left: 2px;
173+
padding-right: 25%;
174+
z-index: 1;
175+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
176+
}
177+
178+
.calendar-header {
179+
display: flex;
180+
justify-content: space-between;
181+
align-items: center;
182+
font-size: 1.0em;
183+
}
184+
185+
.calendar-grid {
186+
display: grid;
187+
grid-template-columns: repeat(7, 1fr);
188+
gap: 2px;
189+
}
190+
191+
.day {
192+
padding: 1px;
193+
text-align: center;
194+
cursor: pointer;
195+
transition: background-color 0.3s;
196+
min-height: 5%;
197+
}
198+
199+
.day.hover {
200+
background-color: rgba(0, 123, 255, 0.5);
201+
}
202+
203+
.day.selected {
204+
background-color: rgba(0, 86, 179, 0.7);
205+
}
25206
</style>

0 commit comments

Comments
 (0)