diff --git a/package-lock.json b/package-lock.json index 9df77ef..3165483 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,18 @@ "@types/react-dom": "^18.2.7", "astro": "^3.0.12", "classnames": "^2.3.2", + "colord": "^2.9.3", "date-fns": "^2.29.3", + "date-fns-tz": "^2.0.0", + "nanoid": "^5.0.4", "prettier": "^3.0.3", "react": "^18.2.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", - "react-use-measure": "^2.1.1" + "react-use-measure": "^2.1.1", + "rrule": "^2.8.1", + "styled-components": "^6.1.1" } }, "node_modules/@ampproject/remapping": { @@ -414,6 +421,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -460,6 +478,24 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -890,6 +926,21 @@ "node": ">= 8" } }, + "node_modules/@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "node_modules/@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "node_modules/@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, "node_modules/@react-spring/animated": { "version": "9.7.3", "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", @@ -1082,6 +1133,11 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "node_modules/@types/stylis": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.4.tgz", + "integrity": "sha512-36ZrGJ8fgtBr6nwNnuJ9jXIj+bn/pF6UoqmrQT7+Y99+tFFeHHsoR54+194dHdyhPjgbeoNz3Qru0oRt0l6ASQ==" + }, "node_modules/@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", @@ -1852,6 +1908,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001557", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001557.tgz", @@ -2069,6 +2133,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "optional": true }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -2109,10 +2178,28 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/date-fns": { "version": "2.29.3", @@ -2126,6 +2213,14 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/date-fns-tz": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz", + "integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==", + "peerDependencies": { + "date-fns": ">=2.0.0" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -2218,6 +2313,16 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "node_modules/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } + }, "node_modules/dset": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", @@ -2374,6 +2479,11 @@ "node": ">=0.10.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -2678,6 +2788,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -3926,9 +4044,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.4.tgz", + "integrity": "sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==", "funding": [ { "type": "github", @@ -3936,10 +4054,10 @@ } ], "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/napi-build-utils": { @@ -4262,9 +4380,9 @@ } }, "node_modules/postcss": { - "version": "8.4.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", - "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "funding": [ { "type": "opencollective", @@ -4280,7 +4398,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -4288,6 +4406,28 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -4515,6 +4655,43 @@ "node": ">=0.10.0" } }, + "node_modules/react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "dependencies": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "@types/hoist-non-react-statics": ">= 3.3.1", + "@types/node": ">= 12", + "@types/react": ">= 16", + "react": ">= 16.14" + }, + "peerDependenciesMeta": { + "@types/hoist-non-react-statics": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "dependencies": { + "dnd-core": "^16.0.1" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4527,6 +4704,11 @@ "react": "^18.2.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/react-use-measure": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz", @@ -4563,6 +4745,19 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/rehype": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz", @@ -4819,6 +5014,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/rrule": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", + "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4926,6 +5129,11 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/sharp": { "version": "0.32.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.5.tgz", @@ -5211,6 +5419,38 @@ "node": ">=0.10.0" } }, + "node_modules/styled-components": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.1.tgz", + "integrity": "sha512-cpZZP5RrKRIClBW5Eby4JM1wElLVP4NQrJbJ0h10TidTyJf4SIIwa3zLXOoPb4gJi8MsJ8mjq5mu2IrEhZIAcQ==", + "dependencies": { + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/unitless": "^0.8.0", + "@types/stylis": "^4.0.2", + "css-to-react-native": "^3.2.0", + "csstype": "^3.1.2", + "postcss": "^8.4.31", + "shallowequal": "^1.1.0", + "stylis": "^4.3.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/stylis": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5345,6 +5585,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6138,6 +6383,14 @@ "@babel/types": "^7.22.15" } }, + "@babel/runtime": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, "@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -6175,6 +6428,24 @@ "to-fast-properties": "^2.0.0" } }, + "@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "requires": { + "@emotion/memoize": "^0.8.1" + } + }, + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -6388,6 +6659,21 @@ "fastq": "^1.6.0" } }, + "@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, "@react-spring/animated": { "version": "9.7.3", "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", @@ -6563,6 +6849,11 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "@types/stylis": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.4.tgz", + "integrity": "sha512-36ZrGJ8fgtBr6nwNnuJ9jXIj+bn/pF6UoqmrQT7+Y99+tFFeHHsoR54+194dHdyhPjgbeoNz3Qru0oRt0l6ASQ==" + }, "@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", @@ -7006,6 +7297,11 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==" }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, "caniuse-lite": { "version": "1.0.30001557", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001557.tgz", @@ -7145,6 +7441,11 @@ "simple-swizzle": "^0.2.2" } }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, "comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -7175,16 +7476,37 @@ "which": "^2.0.1" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "date-fns": { "version": "2.29.3", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" }, + "date-fns-tz": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz", + "integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==", + "requires": {} + }, "debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -7247,6 +7569,16 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "requires": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } + }, "dset": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", @@ -7368,6 +7700,11 @@ "is-extendable": "^0.1.0" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, "fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -7597,6 +7934,14 @@ "space-separated-tokens": "^2.0.0" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -8366,9 +8711,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.4.tgz", + "integrity": "sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==" }, "napi-build-utils": { "version": "1.0.2", @@ -8594,15 +8939,27 @@ } }, "postcss": { - "version": "8.4.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", - "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "requires": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" + }, + "dependencies": { + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + } } }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, "prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -8765,6 +9122,26 @@ "loose-envify": "^1.1.0" } }, + "react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "requires": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + } + }, + "react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "requires": { + "dnd-core": "^16.0.1" + } + }, "react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -8774,6 +9151,11 @@ "scheduler": "^0.23.0" } }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "react-use-measure": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz", @@ -8800,6 +9182,19 @@ "picomatch": "^2.2.1" } }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "rehype": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz", @@ -8979,6 +9374,14 @@ "fsevents": "~2.3.2" } }, + "rrule": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", + "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "requires": { + "tslib": "^2.4.0" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -9045,6 +9448,11 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "sharp": { "version": "0.32.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.5.tgz", @@ -9235,6 +9643,27 @@ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "optional": true }, + "styled-components": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.1.tgz", + "integrity": "sha512-cpZZP5RrKRIClBW5Eby4JM1wElLVP4NQrJbJ0h10TidTyJf4SIIwa3zLXOoPb4gJi8MsJ8mjq5mu2IrEhZIAcQ==", + "requires": { + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/unitless": "^0.8.0", + "@types/stylis": "^4.0.2", + "css-to-react-native": "^3.2.0", + "csstype": "^3.1.2", + "postcss": "^8.4.31", + "shallowequal": "^1.1.0", + "stylis": "^4.3.0", + "tslib": "^2.5.0" + } + }, + "stylis": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -9335,6 +9764,11 @@ } } }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/package.json b/package.json index 302ef44..074feef 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,17 @@ "@types/react-dom": "^18.2.7", "astro": "^3.0.12", "classnames": "^2.3.2", + "colord": "^2.9.3", "date-fns": "^2.29.3", + "date-fns-tz": "^2.0.0", + "nanoid": "^5.0.4", "prettier": "^3.0.3", "react": "^18.2.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", - "react-use-measure": "^2.1.1" + "react-use-measure": "^2.1.1", + "rrule": "^2.8.1", + "styled-components": "^6.1.1" } } diff --git a/public/icons/chevron-down.svg b/public/icons/chevron-down.svg new file mode 100644 index 0000000..a57e6cb --- /dev/null +++ b/public/icons/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/drag.svg b/public/icons/drag.svg new file mode 100644 index 0000000..19a9101 --- /dev/null +++ b/public/icons/drag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/calendar.svg b/public/icons/navigation/calendar.svg new file mode 100644 index 0000000..9191a8c --- /dev/null +++ b/public/icons/navigation/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/help.svg b/public/icons/navigation/help.svg new file mode 100644 index 0000000..5c46dc5 --- /dev/null +++ b/public/icons/navigation/help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/notes.svg b/public/icons/navigation/notes.svg new file mode 100644 index 0000000..d558d84 --- /dev/null +++ b/public/icons/navigation/notes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/settings.svg b/public/icons/navigation/settings.svg new file mode 100644 index 0000000..715a1c1 --- /dev/null +++ b/public/icons/navigation/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/stats.svg b/public/icons/navigation/stats.svg new file mode 100644 index 0000000..1137ecc --- /dev/null +++ b/public/icons/navigation/stats.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/navigation/tasks.svg b/public/icons/navigation/tasks.svg new file mode 100644 index 0000000..867974b --- /dev/null +++ b/public/icons/navigation/tasks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/play.svg b/public/icons/play.svg new file mode 100644 index 0000000..ceb71ad --- /dev/null +++ b/public/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/settings.svg b/public/icons/settings.svg new file mode 100644 index 0000000..ac7e961 --- /dev/null +++ b/public/icons/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/triangle-down.svg b/public/icons/triangle-down.svg new file mode 100644 index 0000000..78ae21b --- /dev/null +++ b/public/icons/triangle-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Accordion/Accordion.module.css b/src/components/Accordion/Accordion.module.css index 81b5ca1..c66653e 100644 --- a/src/components/Accordion/Accordion.module.css +++ b/src/components/Accordion/Accordion.module.css @@ -21,6 +21,16 @@ padding: 0; } +.icon { + display: inline-flex; + vertical-align: middle; + transition: transform 0.3s ease-in-out; +} + +.icon.open { + transform: rotate(180deg); +} + @media screen and (min-width: 769px) { .demo { display: none; diff --git a/src/components/Accordion/Accordion.tsx b/src/components/Accordion/Accordion.tsx index 9757cbb..2a44c79 100644 --- a/src/components/Accordion/Accordion.tsx +++ b/src/components/Accordion/Accordion.tsx @@ -1,6 +1,11 @@ -import React, { useRef, type ReactNode, useLayoutEffect, useState } from "react"; +import React, { + useRef, + type ReactNode, + useLayoutEffect, + useState, +} from "react"; import { animated, useSpring, useTransition } from "@react-spring/web"; -import useMeasure from 'react-use-measure'; +import useMeasure from "react-use-measure"; import cn from "classnames"; import styles from "./Accordion.module.css"; @@ -27,7 +32,14 @@ export const AccordionItem = (props: Props) => { })} >

- {title} + + + {" "} + {title}

{children}
@@ -59,9 +71,7 @@ export const Accordion = (props: AccordionProps) => { onOpen={() => onIndexChange(i)} > {item.content} -
- {item.demo} -
+
{item.demo}
))} diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx new file mode 100644 index 0000000..6c7c7a3 --- /dev/null +++ b/src/components/App/App.tsx @@ -0,0 +1,607 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import styled, { ThemeProvider, useTheme } from "styled-components"; +import { nanoid } from "nanoid"; +import { WeekCalendar } from "../../components/WeekCalendar"; +import { DndProvider } from "react-dnd"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { useCalendarTheme } from "../../hooks/useCalendarTheme"; +import { Sidebar } from "./Sidebar"; +import { light } from "./theme/light"; +import { DragLayer, TASK } from "./DragLayer"; +import { colord } from "colord"; +import { + addDays, + endOfWeek, + format, + intervalToDuration, + isPast, + set, + startOfWeek, +} from "date-fns"; +import { Status, type CalendarEventData, type TTask } from "./types"; +import { TaskStatus } from "../TaskStatus/TaskStatus"; +import { + WeekCalendarView, + type WeekEvent, + type WeekEventDates, + type WeekTimebox, +} from "../WeekCalendar/types"; +import { + CALENDAR_TASK_BLOCK, + CALENDAR_TIMEBOX_BLOCK, +} from "../WeekCalendar/constants"; +import { RRule } from "rrule"; + +export const Root = () => { + return ( + + + + + + ); +}; + +const defaultProjects = { + Personal: { + id: nanoid(), + title: "Personal", + color: "#388e3c", + backgroundColor: "#e8f5e9", + }, + Work: { + id: nanoid(), + title: "Work", + color: "#7b1fa2", + backgroundColor: "#f3e5f5", + }, + Education: { + id: nanoid(), + title: "Education", + color: "#303f9f", + backgroundColor: "#e8eaf6", + }, +}; + +const defaultBacklogTasks = [ + { + id: nanoid(), + title: "Buy cat food", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Make duplicate of the key", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Find a babysitter", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Book a hotel for vacation", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Pay for the internet", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Buy a new phone", + project: defaultProjects["Personal"], + }, + { + id: nanoid(), + title: "Send the report", + project: defaultProjects["Work"], + }, + { + id: nanoid(), + title: "Prepare the presentation", + project: defaultProjects["Work"], + }, + { + id: nanoid(), + title: "Write tests", + project: defaultProjects["Work"], + tasks: [ + { + id: nanoid(), + title: "Unit tests", + project: defaultProjects["Work"], + }, + { + id: nanoid(), + title: "Integration tests", + project: defaultProjects["Work"], + }, + { + id: nanoid(), + title: "E2E tests", + project: defaultProjects["Work"], + }, + ], + }, + { + id: nanoid(), + title: "Refactor the monetization code", + project: defaultProjects["Work"], + }, +]; + +const taskNames = [ + "Complete project proposal", + "Conduct market research", + "Schedule meetings with clients", + "Create a social media strategy", + "Review and revise website content", + "Develop a marketing campaign", + "Analyze data from customer surveys", + "Write a business plan", + "Update employee training manuals", + "Design a new logo", + "Coordinate team training sessions", + "Generate monthly financial reports", + "Implement a customer loyalty program", + "Research new product ideas", + "Conduct performance evaluations", + "Optimize website for search engines", + "Plan company retreat", + "Prepare sales forecast", + "Create promotional materials", + "Review and respond to customer inquiries", + "Conduct competitor analysis", + "Launch new product line", + "Evaluate supplier contracts", + "Develop a content marketing strategy", + "Coordinate trade show participation", + "Improve inventory management system", + "Conduct staff training on new software", + "Organize company-wide event", + "Create email marketing campaign", + "Implement cost-cutting measures", + "Upgrade computer hardware", + "Conduct user testing on website", + "Develop customer relationship management system", + "Write and distribute press releases", + "Conduct customer satisfaction surveys", + "Plan and execute advertising campaign", + "Research and select new vendors", + "Develop sales training program", + "Design and implement employee wellness program", + "Update company website", + "Analyze and interpret sales data", + "Conduct brainstorming sessions", + "Develop customer personas", + "Negotiate contracts with suppliers", + "Create a customer referral program", + "Plan and host industry conference", + "Conduct market segmentation analysis", + "Develop customer onboarding process", + "Update product packaging", + "Analyze website traffic and user behavior", + "Conduct employee engagement survey", + "Develop online learning modules", + "Coordinate product launches", + "Implement data security measures", + "Create standardized procedures and policies", + "Research and recommend project management software", + "Evaluate and select advertising agencies", + "Develop affiliate marketing program", + "Design and conduct customer focus groups", + "Optimize social media profiles", + "Conduct product demonstrations", + "Coordinate public relations activities", + "Conduct risk assessments", + "Develop customer retention strategies", + "Write case studies and success stories", + "Evaluate and recommend CRM software", + "Conduct market trend analysis", + "Develop mobile app", + "Implement customer feedback system", + "Create employee recognition program", + "Update company branding", + "Conduct usability testing", + "Develop pricing strategy", + "Analyze financial statements", + "Plan and execute direct mail campaign", + "Set up and optimize online advertising campaigns", + "Conduct inventory audit", + "Develop customer satisfaction measurement tools", + "Design and conduct training workshops", + "Conduct focus groups for product testing", + "Implement project management methodology", + "Research and recommend email marketing software", + "Develop customer service training program", + "Create and manage social media content calendar", + "Analyze and optimize sales funnels", + "Conduct market research surveys", + "Develop employee performance metrics", + "Coordinate product recalls or returns", + "Implement website analytics tools", + "Create employee handbook", + "Conduct supplier negotiations", + "Develop marketing collateral", + "Update pricing information", + "Conduct customer churn analysis", + "Design and execute customer loyalty program", + "Analyze and optimize email marketing campaigns", + "Conduct competitor pricing analysis", + "Develop lead generation strategies", + "Create customer testimonials", + "Plan and execute product launch event", +]; + +const personalTaskNames = [ + "Go for a run", + "Complete laundry", + "Buy groceries", + "Pay bills", + "Read a book", + "Write in journal", + "Organize closet", + "Meditate", + "Plan meals for the week", + "Call a friend", + "Clean the bathroom", + "Schedule doctor's appointment", + "Learn a new recipe", + "Update budget", + "Take a walk in the park", +]; + +let taskNamesIndex = 0; + +const App = () => { + const [date, setDate] = useState( + startOfWeek(new Date(), { weekStartsOn: 1 }), + ); + const [events, setEvents] = useState[]>( + getEvents({ start: startOfWeek(new Date()), end: endOfWeek(new Date()) }), + ); + const [timeBoxes, setTimeBoxes] = useState([]); + const [range, setRange] = useState(); + const [backlogTasks, setBacklogTasks] = useState(defaultBacklogTasks); + const [timezones] = useState([ + { + label: "Home", + name: Intl.DateTimeFormat().resolvedOptions().timeZone, + isMain: true, + }, + ]); + + useEffect(() => { + if (range) { + setTimeBoxes(getTimeboxes(range)); + } + }, [range]); + + const theme = useTheme(); + + const calendarTheme = useCalendarTheme(); + + const handleAddEvent = (dates: WeekEventDates, task: TTask) => { + setEvents([ + ...events, + { + id: task.id, + data: { + task: { + ...task, + status: Status.IN_PROGRESS, + }, + type: CALENDAR_TASK_BLOCK, + }, + ...dates, + }, + ]); + + setBacklogTasks((backlogTasks) => + backlogTasks.map((t) => { + if (t.id === task.id) { + return { + ...t, + status: Status.IN_PROGRESS, + }; + } else { + return t; + } + }), + ); + + return Promise.resolve(true); + }; + + const handleEventAddRequest = (dates: WeekEventDates) => { + const projectName = (["Personal", "Work", "Education"] as const)[ + Math.floor(getRandomArbitrary(0, 3)) + ]; + + setEvents([ + ...events, + { + id: nanoid(), + ...dates, + data: { + task: { + id: nanoid(), + title: taskNames[taskNamesIndex++], + status: Status.IN_PROGRESS, + project: defaultProjects[projectName], + }, + type: CALENDAR_TASK_BLOCK, + }, + }, + ]); + }; + + const handleEventChange = (dates: WeekEventDates, event: WeekEvent) => { + setEvents( + events.map((e) => { + if (e.id === event.id) { + return { + ...e, + ...dates, + }; + } else { + return e; + } + }), + ); + }; + + const handleUpdateStatus = (taskId: string, status: Status) => {}; + + const renderDayInfo = useCallback((date: Date, events: WeekEvent[]) => { + const time = events.reduce((acc, event) => { + if (!event.startDateTime || !event.endDateTime) { + return acc; + } + + const duration = intervalToDuration({ + start: event.startDateTime, + end: event.endDateTime, + }); + + return acc + (duration.hours || 0) * 60 + (duration.minutes || 0); + }, 0); + + const hours = Math.floor(time / 60); + const minutes = time % 60; + + if (time === 0) { + return null; + } + + return ( + + {hours}h {minutes}m + + ); + }, []); + + const renderEvent = useCallback( + (event: WeekEvent, dates: WeekEventDates) => { + const backgroundColor = colord( + event.data.task?.project.backgroundColor || theme.eventBackgroundColor, + ) + .alpha(event ? 0.75 : 1) + .toHex(); + const color = event.data.task?.project.color || "#444"; + + let duration, h, m, d; + + if (event.startDateTime && event.endDateTime) { + duration = intervalToDuration({ + start: dates.startDateTime || event.startDateTime, + end: dates.endDateTime || event.endDateTime, + }); + + h = duration.hours ? `${duration.hours}h` : ""; + m = duration.minutes ? `${duration.minutes}m` : ""; + d = duration.days ? `${duration.days}d` : ""; + } + + const status = event.data.task ? ( + + + + ) : null; + + return ( + + + {status} + {event.data.task?.title} + +
+ {format((dates.startDateTime || event.startDateTime)!, "HH:mm")} + {" - "} + {format((dates.endDateTime || event.endDateTime)!, "HH:mm")} ( + {`${d} ${h} ${m}`.trim()}) +
+
+ ); + }, + [], + ); + + return ( + +