This commit is contained in:
Zachary
2024-11-11 18:19:45 +01:00
parent 4216b83837
commit 1c52afa674
5 changed files with 306 additions and 233 deletions

View File

@@ -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>