Cleanup
This commit is contained in:
@@ -17,14 +17,8 @@
|
||||
let optimizedDaysOff = [];
|
||||
let consecutiveDaysOff = [];
|
||||
let placeholder = "Country";
|
||||
let isFirstClick = true;
|
||||
let inputElement;
|
||||
|
||||
function handleYearChange(event) {
|
||||
year = parseInt(event.target.value);
|
||||
updateHolidays();
|
||||
}
|
||||
|
||||
function handleCountryChange(event) {
|
||||
const fullValue = event.target.value;
|
||||
const countryCode = Object.keys(countriesList).find(code => countriesList[code] === fullValue);
|
||||
@@ -43,7 +37,7 @@
|
||||
tempSpan.style.whiteSpace = 'nowrap';
|
||||
tempSpan.textContent = inputElement.value || inputElement.placeholder;
|
||||
document.body.appendChild(tempSpan);
|
||||
inputElement.style.width = `${tempSpan.offsetWidth + 30}px`;
|
||||
inputElement.style.width = `${tempSpan.offsetWidth + 50}px`;
|
||||
document.body.removeChild(tempSpan);
|
||||
}
|
||||
|
||||
@@ -53,34 +47,15 @@
|
||||
holidays = getHolidaysForYear(countryCode, year);
|
||||
optimizedDaysOff = optimizeDaysOff(holidays, year, daysOff);
|
||||
consecutiveDaysOff = calculateConsecutiveDaysOff(holidays, optimizedDaysOff, year);
|
||||
} else {
|
||||
holidays = [];
|
||||
optimizedDaysOff = [];
|
||||
consecutiveDaysOff = [];
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
switch (event.key) {
|
||||
case 'ArrowRight':
|
||||
event.preventDefault();
|
||||
year++;
|
||||
updateHolidays();
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
event.preventDefault();
|
||||
year--;
|
||||
updateHolidays();
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
daysOff++;
|
||||
updateHolidays();
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (daysOff > 0) {
|
||||
daysOff--;
|
||||
updateHolidays();
|
||||
}
|
||||
break;
|
||||
}
|
||||
console.log('Year:', year);
|
||||
console.log('Holidays updated:', holidays);
|
||||
console.log('Optimized Days Off:', optimizedDaysOff);
|
||||
console.log('Consecutive Days Off:', consecutiveDaysOff);
|
||||
}
|
||||
|
||||
function getFlagEmoji(countryCode) {
|
||||
@@ -89,81 +64,98 @@
|
||||
.replace(/./g, char => String.fromCodePoint(127397 + char.charCodeAt()));
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
switch (event.key) {
|
||||
case 'ArrowRight':
|
||||
event.preventDefault();
|
||||
year++;
|
||||
updateHolidays(); // Recalculate holidays for the new year
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
event.preventDefault();
|
||||
year--;
|
||||
updateHolidays(); // Recalculate holidays for the new year
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
daysOff++;
|
||||
updateHolidays(); // Recalculate holidays with updated days off
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (daysOff > 0) {
|
||||
daysOff--;
|
||||
updateHolidays(); // Recalculate holidays with updated days off
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
adjustInputWidth(inputElement);
|
||||
inputElement.addEventListener('input', () => adjustInputWidth(inputElement));
|
||||
inputElement.addEventListener('input', () => {
|
||||
adjustInputWidth(inputElement);
|
||||
const countryCode = Object.keys(countriesList).find(code => countriesList[code] === inputElement.value);
|
||||
});
|
||||
inputElement.addEventListener('focus', () => {
|
||||
inputElement.value = '';
|
||||
adjustInputWidth(inputElement);
|
||||
});
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
});
|
||||
|
||||
updateHolidays();
|
||||
console.log(consecutiveDaysOff);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
header, footer {
|
||||
.header {
|
||||
max-width: 800px;
|
||||
margin: 40px auto;
|
||||
text-align: center;
|
||||
color: #e0e0e0; /* Monochrome light text */
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #333; /* Subtle border for separation */
|
||||
}
|
||||
|
||||
h1 {
|
||||
.header h2 {
|
||||
font-size: 2.5em; /* Slightly larger font size */
|
||||
margin: 0;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
footer {
|
||||
border-top: 1px solid #333;
|
||||
font-size: 0.9em;
|
||||
.header p {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
max-width: 900px;
|
||||
margin: 20px auto;
|
||||
padding: 10px 0;
|
||||
background-color: #1e1e1e; /* Slightly lighter dark background for content boxes */
|
||||
max-width: 1200px;
|
||||
margin: 40px auto;
|
||||
padding: 20px;
|
||||
background-color: #111;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content-box p {
|
||||
text-align: center;
|
||||
font-size: 1em; /* Slightly smaller font size */
|
||||
color: #e0e0e0; /* Light gray text */
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.7);
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 0 10px;
|
||||
font-size: 0.9em; /* Slightly smaller font size */
|
||||
font-size: 1em;
|
||||
padding: 8px;
|
||||
background-color: #2a2a2a; /* Darker gray for inputs */
|
||||
color: #e0e0e0; /* Light text for inputs */
|
||||
border: 1px solid #444;
|
||||
background-color: transparent;
|
||||
border: 1px solid #555;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s;
|
||||
width: auto; /* Dynamic width based on content */
|
||||
color: #fff;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
input::hover {
|
||||
background-color: #333; /* Slightly lighter on hover */
|
||||
input:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 15px 0;
|
||||
padding: 15px;
|
||||
background-color: #2a2a2a;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
input:focus {
|
||||
outline: 2px solid #61dafb;
|
||||
}
|
||||
|
||||
.calendar-grid {
|
||||
@@ -174,83 +166,40 @@
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@media (max-width: 1024px) {
|
||||
.calendar-grid {
|
||||
grid-template-columns: repeat(2, 1fr); /* 2 columns on smaller screens */
|
||||
grid-template-columns: repeat(2, 1fr); /* Adjust to 2 columns for medium screens */
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.calendar-grid {
|
||||
grid-template-columns: repeat(2, 1fr); /* Allow 2 columns on smaller screens */
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.calendar-grid {
|
||||
grid-template-columns: repeat(1, 1fr); /* Adjust to 1 column for very small screens */
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-container {
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
background-color: #2a2a2a; /* Dark gray for calendar */
|
||||
color: #e0e0e0;
|
||||
max-width: 300px;
|
||||
background-color: #111;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.editable-input {
|
||||
border: none;
|
||||
border-bottom: 1px dotted #e0e0e0;
|
||||
background: none;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
text-align: center;
|
||||
margin: 0 10px;
|
||||
outline: none;
|
||||
transition: width 0.2s;
|
||||
-webkit-appearance: none; /* Remove default styling */
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: #e0e0e0; /* Default text color */
|
||||
}
|
||||
|
||||
.editable-input::placeholder {
|
||||
color: #a0a0a0; /* Slightly grayer text for placeholder */
|
||||
}
|
||||
|
||||
.arrow-controls {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #444;
|
||||
color: #e0e0e0;
|
||||
font-size: 1em; /* Slightly smaller font size */
|
||||
cursor: pointer;
|
||||
padding: 5px 10px;
|
||||
margin: 0 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
transition: background-color 0.3s, color 0.3s, transform 0.1s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #333;
|
||||
color: #fff; /* Change color on hover */
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: translateY(2px); /* Simulate button press */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 2px solid #61dafb; /* Accessibility focus outline */
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.flag {
|
||||
font-size: 2em; /* Adjust the size as needed */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
overflow: visible;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.calendar-key {
|
||||
@@ -258,9 +207,8 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #1e1e1e;
|
||||
border-radius: 5px;
|
||||
color: #e0e0e0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.key-item {
|
||||
@@ -277,7 +225,7 @@
|
||||
}
|
||||
|
||||
.color-box.weekend {
|
||||
background-color: #333;
|
||||
background-color: #585858; /* Muted gray/white */
|
||||
}
|
||||
|
||||
.color-box.optimized {
|
||||
@@ -287,18 +235,91 @@
|
||||
.color-box.holiday {
|
||||
background-color: #3b1e6e;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: #c5c6c7;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #66fcf1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.arrow-controls {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #333;
|
||||
border: 1px solid #444;
|
||||
color: #fff;
|
||||
font-size: 1em;
|
||||
cursor: pointer;
|
||||
padding: 5px 10px;
|
||||
margin: 0 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
transition: background-color 0.3s, color 0.3s, transform 0.1s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 2px solid #61dafb;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.flag {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.day {
|
||||
aspect-ratio: 1;
|
||||
text-align: center;
|
||||
font-size: 0.7em; /* Adjust font size for smaller screens */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ddd;
|
||||
background-color: #222;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
<header>
|
||||
<h1>Stretch My Time Off</h1>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="header">
|
||||
<h2>Stretch My Time Off</h2>
|
||||
<p>
|
||||
In {selectedCountry}, there are {holidays.length} public holidays in {year}.
|
||||
<br />
|
||||
Let's stretch your {daysOff} days off to {consecutiveDaysOff.reduce((total, group) => total + group.totalDays, 0)} vacation days.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="content-box">
|
||||
<p>
|
||||
I live in
|
||||
<span class="flag">{getFlagEmoji(Object.keys(countriesList).find(code => countriesList[code] === selectedCountry))}</span>
|
||||
<input bind:this={inputElement} list="countries" class="editable-input bold" bind:value={selectedCountry} placeholder={placeholder} on:input={adjustInputWidth} on:focus={() => { inputElement.value = ''; adjustInputWidth(); }} on:change={handleCountryChange} aria-label="Select country" />
|
||||
<span class="flag" style="vertical-align: middle;">{getFlagEmoji(Object.keys(countriesList).find(code => countriesList[code] === selectedCountry))}</span>
|
||||
<input bind:this={inputElement} list="countries" class="editable-input bold" bind:value={selectedCountry} placeholder={placeholder} on:input={handleCountryChange} on:focus={() => { inputElement.value = ''; adjustInputWidth(); }} aria-label="Select country" />
|
||||
and have
|
||||
<span class="arrow-controls">
|
||||
<button on:click={() => { daysOff++; updateHolidays(); }} aria-label="Increase days off">▲</button>
|
||||
@@ -319,7 +340,7 @@
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div class="content-box">
|
||||
<div class="content-box" id="calendar">
|
||||
<div class="calendar-key">
|
||||
<div class="key-item">
|
||||
<span class="color-box weekend"></span> Weekend
|
||||
@@ -334,7 +355,7 @@
|
||||
<div class="calendar-grid">
|
||||
{#each months as month}
|
||||
<div class="calendar-container">
|
||||
<CalendarMonth {year} {month} {holidays} {optimizedDaysOff} />
|
||||
<CalendarMonth {year} {month} {holidays} {optimizedDaysOff} {consecutiveDaysOff} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -342,5 +363,5 @@
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>© { new Date().getFullYear() } Stretch My Time Off. All rights reserved.</p>
|
||||
<p>Made with <span style="color: red;">📅</span> by <a href="https://zach.ie" target="_blank">Zach</a></p>
|
||||
</footer>
|
||||
Reference in New Issue
Block a user