Add initial commit
This commit is contained in:
171
package-lock.json
generated
171
package-lock.json
generated
@@ -7,6 +7,10 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "stretch-my-time-off",
|
"name": "stretch-my-time-off",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"date-holidays": "^3.23.12",
|
||||||
|
"i18n-iso-countries": "^7.13.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
@@ -857,6 +861,12 @@
|
|||||||
"acorn": ">=8.9.0"
|
"acorn": ">=8.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
|
"license": "Python-2.0"
|
||||||
|
},
|
||||||
"node_modules/aria-query": {
|
"node_modules/aria-query": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
|
||||||
@@ -867,6 +877,15 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/astronomia": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/astronomia/-/astronomia-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-TcJD9lUC5eAo0/Ji7rnQauX/yQbi0yZWM+JsNr77W3OA5fsrgvuFgubLMFwfw4VlZ29cu9dG/yfJbfvuTSftjg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
@@ -877,6 +896,18 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/caldate": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/caldate/-/caldate-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-JndhrUuDuE975KUhFqJaVR1OQkCHZqpOrJur/CFXEIEhWhBMjxO85cRSK8q4FW+B+yyPq6GYua2u4KvNzTcq0w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"moment-timezone": "^0.5.43"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
|
||||||
@@ -903,6 +934,73 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/date-bengali-revised": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-bengali-revised/-/date-bengali-revised-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-q9iDru4+TSA9k4zfm0CFHJj6nBsxP7AYgWC/qodK/i7oOIlj5K2z5IcQDtESfs/Qwqt/xJYaP86tkazd/vRptg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/date-chinese": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-chinese/-/date-chinese-2.1.4.tgz",
|
||||||
|
"integrity": "sha512-WY+6+Qw92ZGWFvGtStmNQHEYpNa87b8IAQ5T8VKt4wqrn24lBXyyBnWI5jAIyy7h/KVwJZ06bD8l/b7yss82Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"astronomia": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/date-easter": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-easter/-/date-easter-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-aOViyIgpM4W0OWUiLqivznwTtuMlD/rdUWhc5IatYnplhPiWrLv75cnifaKYhmQwUBLAMWLNG4/9mlLIbXoGBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/date-holidays": {
|
||||||
|
"version": "3.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-holidays/-/date-holidays-3.23.12.tgz",
|
||||||
|
"integrity": "sha512-DLyP0PPVgNydgaTAY7SBS26+5h3KO1Z8FRKiAROkz0hAGNBLGAM48SMabfVa2ACRHH7Qw3LXYvlJkt9oa9WePA==",
|
||||||
|
"license": "(ISC AND CC-BY-3.0)",
|
||||||
|
"dependencies": {
|
||||||
|
"date-holidays-parser": "^3.4.4",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"prepin": "^1.0.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"holidays2json": "scripts/holidays2json.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/date-holidays-parser": {
|
||||||
|
"version": "3.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-holidays-parser/-/date-holidays-parser-3.4.4.tgz",
|
||||||
|
"integrity": "sha512-R5aO4oT8H51ZKdvApqHrqYEiNBrqT6tRj2PFXNcZfqMI4nxY7KKKly0ZsmquR5gY+x9ldKR8SAMdozzIInaoXg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"astronomia": "^4.1.1",
|
||||||
|
"caldate": "^2.0.5",
|
||||||
|
"date-bengali-revised": "^2.0.2",
|
||||||
|
"date-chinese": "^2.1.4",
|
||||||
|
"date-easter": "^1.0.2",
|
||||||
|
"deepmerge": "^4.3.1",
|
||||||
|
"jalaali-js": "^1.2.6",
|
||||||
|
"moment-timezone": "^0.5.43"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.7",
|
"version": "4.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||||
@@ -925,7 +1023,6 @@
|
|||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -938,6 +1035,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/diacritics": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||||
@@ -1039,6 +1142,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/i18n-iso-countries": {
|
||||||
|
"version": "7.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.13.0.tgz",
|
||||||
|
"integrity": "sha512-pVh4CjdgAHZswI98hzG+1BItQlsQfR+yGDsjDISoWIV/jHDAvCmSyZ5vj2YWwAjfVZ8/BhBDqWcFvuGOyHe4vg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"diacritics": "1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/import-meta-resolve": {
|
"node_modules/import-meta-resolve": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
|
||||||
@@ -1060,6 +1175,24 @@
|
|||||||
"@types/estree": "*"
|
"@types/estree": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jalaali-js": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-gE+YHWSbygYAoJa+Xg8LWxGILqFOxZSBQQw39ghel01fVFUxV7bjL0x1JFsHcLQ3uPjvn81HQMa+kxwyPWnxGQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
@@ -1077,6 +1210,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.12",
|
"version": "0.30.12",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
||||||
@@ -1087,6 +1226,27 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/moment-timezone": {
|
||||||
|
"version": "0.5.46",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
|
||||||
|
"integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.29.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
@@ -1169,6 +1329,15 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prepin": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prepin/-/prepin-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-0XL2hreherEEvUy0fiaGEfN/ioXFV+JpImqIzQjxk6iBg4jQ2ARKqvC4+BmRD8w/pnpD+lbxvh0Ub+z7yBEjvA==",
|
||||||
|
"license": "Unlicense",
|
||||||
|
"bin": {
|
||||||
|
"prepin": "bin/prepin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
||||||
|
|||||||
@@ -17,5 +17,9 @@
|
|||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^5.0.3"
|
"vite": "^5.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"date-holidays": "^3.23.12",
|
||||||
|
"i18n-iso-countries": "^7.13.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body style="margin: 0; font-family: Arial, sans-serif; background-color: black; color: white;">
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,2 +1,231 @@
|
|||||||
<h1>Welcome to SvelteKit</h1>
|
<script>
|
||||||
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
import countries from 'i18n-iso-countries';
|
||||||
|
import enLocale from 'i18n-iso-countries/langs/en.json';
|
||||||
|
import CalendarMonth from '../lib/CalendarMonth.svelte';
|
||||||
|
import Holidays from 'date-holidays';
|
||||||
|
|
||||||
|
countries.registerLocale(enLocale);
|
||||||
|
let countriesList = countries.getNames('en');
|
||||||
|
|
||||||
|
let year = new Date().getFullYear();
|
||||||
|
let months = Array.from({ length: 12 }, (_, i) => i);
|
||||||
|
let selectedCountry = 'Belgium'; // Default country name
|
||||||
|
let holidays = [];
|
||||||
|
let daysOff = 24; // Default days off per year
|
||||||
|
let optimizedDaysOff = [];
|
||||||
|
|
||||||
|
function handleYearChange(event) {
|
||||||
|
year = parseInt(event.target.value);
|
||||||
|
updateHolidays();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCountryChange(event) {
|
||||||
|
const countryName = event.target.value;
|
||||||
|
const countryCode = Object.keys(countriesList).find(code => countriesList[code] === countryName);
|
||||||
|
if (countryCode) {
|
||||||
|
selectedCountry = countryName;
|
||||||
|
updateHolidays();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHolidays() {
|
||||||
|
const countryCode = Object.keys(countriesList).find(code => countriesList[code] === selectedCountry);
|
||||||
|
if (countryCode) {
|
||||||
|
const hd = new Holidays(countryCode);
|
||||||
|
holidays = hd.getHolidays(year)
|
||||||
|
.filter(holiday => holiday.type === 'public') // Filter for public holidays
|
||||||
|
.map(holiday => ({
|
||||||
|
date: new Date(holiday.date),
|
||||||
|
name: holiday.name
|
||||||
|
}));
|
||||||
|
console.log('Holidays:', holidays);
|
||||||
|
optimizeDaysOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDaysOffChange(event) {
|
||||||
|
const value = parseInt(event.target.textContent);
|
||||||
|
if (!isNaN(value)) {
|
||||||
|
daysOff = value;
|
||||||
|
optimizeDaysOff();
|
||||||
|
} else {
|
||||||
|
event.target.textContent = daysOff; // Revert to previous valid value if input is invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDaysOffInput(event) {
|
||||||
|
const value = event.target.textContent;
|
||||||
|
event.target.textContent = value.replace(/\D/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function optimizeDaysOff() {
|
||||||
|
// Reset optimized days off
|
||||||
|
optimizedDaysOff = [];
|
||||||
|
|
||||||
|
// Combine holidays and weekends
|
||||||
|
const allDays = holidays.map(h => h.date);
|
||||||
|
let daysToUse = daysOff;
|
||||||
|
|
||||||
|
for (let month = 0; month < 12; month++) {
|
||||||
|
let currentStreak = [];
|
||||||
|
let maxStreak = [];
|
||||||
|
let maxStreakStart = null;
|
||||||
|
|
||||||
|
for (let day = 1; day <= 31; day++) {
|
||||||
|
const date = new Date(year, month, day);
|
||||||
|
if (date.getMonth() !== month) break; // Skip invalid dates
|
||||||
|
|
||||||
|
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
|
||||||
|
const isHoliday = allDays.some(d => d.getTime() === date.getTime());
|
||||||
|
|
||||||
|
if (isWeekend || isHoliday) {
|
||||||
|
currentStreak.push(date);
|
||||||
|
} else {
|
||||||
|
if (currentStreak.length > maxStreak.length) {
|
||||||
|
maxStreak = [...currentStreak];
|
||||||
|
maxStreakStart = currentStreak[0];
|
||||||
|
}
|
||||||
|
currentStreak = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use days off to extend the longest streak in the current month
|
||||||
|
if (maxStreakStart && daysToUse > 0) {
|
||||||
|
let date = new Date(maxStreakStart);
|
||||||
|
while (daysToUse > 0 && date.getFullYear() === year) {
|
||||||
|
date.setDate(date.getDate() - 1);
|
||||||
|
if (!allDays.some(d => d.getTime() === date.getTime()) && date.getDay() !== 0 && date.getDay() !== 6) {
|
||||||
|
optimizedDaysOff.push(new Date(date));
|
||||||
|
daysToUse--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Optimized Days Off:', optimizedDaysOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize holidays on load
|
||||||
|
updateHolidays();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
text-align: center;
|
||||||
|
background-color: black;
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
font-size: 2em;
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #333; /* Dark gray for main background */
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: white; /* Ensure text is white for readability */
|
||||||
|
border-radius: 10px; /* Add border-radius for a smoother look */
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Add shadow for depth */
|
||||||
|
}
|
||||||
|
select, input {
|
||||||
|
margin: 0 5px;
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #555; /* Darker background for inputs */
|
||||||
|
color: white; /* White text for inputs */
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none; /* Remove bullet points */
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.calendar-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* Adjust to fit available space */
|
||||||
|
gap: 10px;
|
||||||
|
justify-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.calendar-container {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
background-color: #444; /* Slightly lighter gray for calendar */
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box; /* Ensure padding is included in width */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Media query for smaller screens */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.calendar-grid {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); /* Adjust for smaller screens */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-span {
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px dotted white; /* Dotted underline */
|
||||||
|
color: white;
|
||||||
|
font-size: 1em;
|
||||||
|
width: 3em; /* Adjust width as needed */
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 5px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-span:focus {
|
||||||
|
border-bottom: 1px solid white; /* Solid underline on focus */
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: #4caf50; /* Green color for highlighting */
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
I live in
|
||||||
|
<input list="countries" bind:value={selectedCountry} on:change={handleCountryChange} />
|
||||||
|
<datalist id="countries">
|
||||||
|
{#each Object.values(countriesList) as name}
|
||||||
|
<option value={name}></option>
|
||||||
|
{/each}
|
||||||
|
</datalist>
|
||||||
|
and have
|
||||||
|
<span contenteditable="true" class="editable-span" on:input={handleDaysOffInput} on:blur={handleDaysOffChange}>{daysOff}</span> days off per year
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="year">Select Year: </label>
|
||||||
|
<input type="number" id="year" bind:value={year} on:input={handleYearChange} min="1900" max="2100" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
There are {holidays.length} public holidays in {selectedCountry}:
|
||||||
|
<ul>
|
||||||
|
{#each holidays as holiday}
|
||||||
|
<li class={optimizedDaysOff.some(d => d.getTime() === holiday.date.getTime()) ? 'highlight' : ''}>
|
||||||
|
{holiday.name} on {formatDate(holiday.date)}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="calendar-grid">
|
||||||
|
{#each months as month}
|
||||||
|
<div class="calendar-container">
|
||||||
|
<CalendarMonth {year} {month} {holidays} {optimizedDaysOff} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
Reference in New Issue
Block a user