-
- {/*
*/}
+
+ {NavsIcons['expand-nav']}
{
expand &&
@@ -66,21 +90,12 @@ export default function NavBar() {
}
-
- {
- NavsContent.map((navContent: string, i: number) => {
- return (
-
-
-
- {NavsIcons[i]}
- {expand &&
{navContent}
}
-
-
-
- )
- })
- }
+
{ if (!expand) setTimeout(() => setExpand(true), 500) }}
+ onMouseLeave={() => { setExpand(!clickToExpand) }}
+ >
+
)
diff --git a/package-lock.json b/package-lock.json
index 7916496..33d09c7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@ant-design/icons": "^5.2.6",
+ "@formkit/auto-animate": "^0.8.0",
"@reduxjs/toolkit": "^1.9.7",
"@types/node": "20.6.2",
"@types/react": "18.2.22",
@@ -17,14 +18,22 @@
"autoprefixer": "10.4.15",
"eslint": "8.49.0",
"eslint-config-next": "13.4.19",
- "next": "13.4.19",
+ "invert-color": "^2.0.0",
+ "lighten-darken-color": "^1.0.0",
+ "lodash": "^4.17.21",
+ "next": "^13.5.5",
"postcss": "8.4.30",
"react": "18.2.0",
+ "react-countdown-circle-timer": "^3.2.1",
"react-dom": "18.2.0",
"react-icons": "^4.11.0",
"react-redux": "^8.1.3",
+ "tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
+ },
+ "devDependencies": {
+ "@types/lodash": "^4.14.200"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -192,6 +201,11 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@formkit/auto-animate": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-0.8.0.tgz",
+ "integrity": "sha512-G8f7489ka0mWyi+1IEZT+xgIwcpWtRMmE2x+IrVoQ+KM1cP6VDj/TbujZjwxdb0P8w8b16/qBfViRmydbYHwMw=="
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.11",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
@@ -266,9 +280,9 @@
}
},
"node_modules/@next/env": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.19.tgz",
- "integrity": "sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ=="
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.5.tgz",
+ "integrity": "sha512-agvIhYWp+ilbScg81s/sLueZo8CNEYLjNOqhISxheLmD/AQI4/VxV7bV76i/KzxH4iHy/va0YS9z0AOwGnw4Fg=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "13.4.19",
@@ -279,9 +293,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz",
- "integrity": "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.5.tgz",
+ "integrity": "sha512-FvTdcJdTA7H1FGY8dKPPbf/O0oDC041/znHZwXA7liiGUhgw5hOQ+9z8tWvuz0M5a/SDjY/IRPBAb5FIFogYww==",
"cpu": [
"arm64"
],
@@ -294,9 +308,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz",
- "integrity": "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.5.tgz",
+ "integrity": "sha512-mTqNIecaojmyia7appVO2QggBe1Z2fdzxgn6jb3x9qlAk8yY2sy4MAcsj71kC9RlenCqDmr9vtC/ESFf110TPA==",
"cpu": [
"x64"
],
@@ -309,9 +323,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz",
- "integrity": "sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.5.tgz",
+ "integrity": "sha512-U9e+kNkfvwh/T8yo+xcslvNXgyMzPPX1IbwCwnHHFmX5ckb1Uc3XZSInNjFQEQR5xhJpB5sFdal+IiBIiLYkZA==",
"cpu": [
"arm64"
],
@@ -324,9 +338,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz",
- "integrity": "sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.5.tgz",
+ "integrity": "sha512-h7b58eIoNCSmKVC5fr167U0HWZ/yGLbkKD9wIller0nGdyl5zfTji0SsPKJvrG8jvKPFt2xOkVBmXlFOtuKynw==",
"cpu": [
"arm64"
],
@@ -339,9 +353,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz",
- "integrity": "sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.5.tgz",
+ "integrity": "sha512-6U4y21T1J6FfcpM9uqzBJicxycpB5gJKLyQ3g6KOfBzT8H1sMwfHTRrvHKB09GIn1BCRy5YJHrA1G26DzqR46w==",
"cpu": [
"x64"
],
@@ -354,9 +368,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz",
- "integrity": "sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.5.tgz",
+ "integrity": "sha512-OuqWSAQHJQM2EsapPFTSU/FLQ0wKm7UeRNatiR/jLeCe1V02aB9xmzuWYo2Neaxxag4rss3S8fj+lvMLzwDaFA==",
"cpu": [
"x64"
],
@@ -369,9 +383,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz",
- "integrity": "sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.5.tgz",
+ "integrity": "sha512-+yLrOZIIZDY4uGn9bLOc0wTgs+M8RuOUFSUK3BhmcLav9e+tcAj0jyBHD4aXv2qWhppUeuYMsyBo1I58/eE6Dg==",
"cpu": [
"arm64"
],
@@ -384,9 +398,9 @@
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz",
- "integrity": "sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.5.tgz",
+ "integrity": "sha512-SyMxXyJtf9ScMH0Dh87THJMXNFvfkRAk841xyW9SeOX3KxM1buXX3hN7vof4kMGk0Yg996OGsX+7C9ueS8ugsw==",
"cpu": [
"ia32"
],
@@ -399,9 +413,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz",
- "integrity": "sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.5.tgz",
+ "integrity": "sha512-n5KVf2Ok0BbLwofAaHiiKf+BQCj1M8WmTujiER4/qzYAVngnsNSjqEWvJ03raeN9eURqxDO+yL5VRoDrR33H9A==",
"cpu": [
"x64"
],
@@ -586,9 +600,9 @@
"integrity": "sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg=="
},
"node_modules/@swc/helpers": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz",
- "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==",
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
+ "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
"dependencies": {
"tslib": "^2.4.0"
}
@@ -607,6 +621,12 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
+ "node_modules/@types/lodash": {
+ "version": "4.14.200",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz",
+ "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==",
+ "dev": true
+ },
"node_modules/@types/node": {
"version": "20.6.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz",
@@ -2467,6 +2487,11 @@
"node": ">= 0.4"
}
},
+ "node_modules/invert-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-color/-/invert-color-2.0.0.tgz",
+ "integrity": "sha512-9s6IATlhOAr0/0MPUpLdMpk81ixIu8IqwPwORssXBauFT/4ff/iyEOcojd0UYuPwkDbJvL1+blIZGhqVIaAm5Q=="
+ },
"node_modules/is-array-buffer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
@@ -2894,6 +2919,11 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lighten-darken-color": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lighten-darken-color/-/lighten-darken-color-1.0.0.tgz",
+ "integrity": "sha512-rKToRUNvcIJGuT+Zd/ljNb83wwJPc4V4HNxYuqIdizQHt3avilV6H1rq2feaxruJBpAIbE1ZJ8wX7BKjTylIsA=="
+ },
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@@ -2921,6 +2951,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -3025,35 +3060,34 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
"node_modules/next": {
- "version": "13.4.19",
- "resolved": "https://registry.npmjs.org/next/-/next-13.4.19.tgz",
- "integrity": "sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==",
+ "version": "13.5.5",
+ "resolved": "https://registry.npmjs.org/next/-/next-13.5.5.tgz",
+ "integrity": "sha512-LddFJjpfrtrMMw8Q9VLhIURuSidiCNcMQjRqcPtrKd+Fx07MsG7hYndJb/f2d3I+mTbTotsTJfCnn0eZ/YPk8w==",
"dependencies": {
- "@next/env": "13.4.19",
- "@swc/helpers": "0.5.1",
+ "@next/env": "13.5.5",
+ "@swc/helpers": "0.5.2",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001406",
- "postcss": "8.4.14",
+ "postcss": "8.4.31",
"styled-jsx": "5.1.1",
- "watchpack": "2.4.0",
- "zod": "3.21.4"
+ "watchpack": "2.4.0"
},
"bin": {
"next": "dist/bin/next"
},
"engines": {
- "node": ">=16.8.0"
+ "node": ">=16.14.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "13.4.19",
- "@next/swc-darwin-x64": "13.4.19",
- "@next/swc-linux-arm64-gnu": "13.4.19",
- "@next/swc-linux-arm64-musl": "13.4.19",
- "@next/swc-linux-x64-gnu": "13.4.19",
- "@next/swc-linux-x64-musl": "13.4.19",
- "@next/swc-win32-arm64-msvc": "13.4.19",
- "@next/swc-win32-ia32-msvc": "13.4.19",
- "@next/swc-win32-x64-msvc": "13.4.19"
+ "@next/swc-darwin-arm64": "13.5.5",
+ "@next/swc-darwin-x64": "13.5.5",
+ "@next/swc-linux-arm64-gnu": "13.5.5",
+ "@next/swc-linux-arm64-musl": "13.5.5",
+ "@next/swc-linux-x64-gnu": "13.5.5",
+ "@next/swc-linux-x64-musl": "13.5.5",
+ "@next/swc-win32-arm64-msvc": "13.5.5",
+ "@next/swc-win32-ia32-msvc": "13.5.5",
+ "@next/swc-win32-x64-msvc": "13.5.5"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -3071,9 +3105,9 @@
}
},
"node_modules/next/node_modules/postcss": {
- "version": "8.4.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
- "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
@@ -3082,10 +3116,14 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
- "nanoid": "^3.3.4",
+ "nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
@@ -4126,6 +4164,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-countdown-circle-timer": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/react-countdown-circle-timer/-/react-countdown-circle-timer-3.2.1.tgz",
+ "integrity": "sha512-yBAy/9ILXOiFbLBM+3jS72TW5LeRcH8wkRC9NNqMpUkCXkGjSnaeRbJMsR9lsYF0oVXjSDbJaRbCuVMT+9HnKA==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -4670,6 +4716,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/tailwind-merge": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz",
+ "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
"node_modules/tailwindcss": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
@@ -5079,14 +5134,6 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
- },
- "node_modules/zod": {
- "version": "3.21.4",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
- "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
}
}
}
diff --git a/package.json b/package.json
index fb9d9fa..9509ea5 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
},
"dependencies": {
"@ant-design/icons": "^5.2.6",
+ "@formkit/auto-animate": "^0.8.0",
"@reduxjs/toolkit": "^1.9.7",
"@types/node": "20.6.2",
"@types/react": "18.2.22",
@@ -18,13 +19,21 @@
"autoprefixer": "10.4.15",
"eslint": "8.49.0",
"eslint-config-next": "13.4.19",
- "next": "13.4.19",
+ "invert-color": "^2.0.0",
+ "lighten-darken-color": "^1.0.0",
+ "lodash": "^4.17.21",
+ "next": "^13.5.5",
"postcss": "8.4.30",
"react": "18.2.0",
+ "react-countdown-circle-timer": "^3.2.1",
"react-dom": "18.2.0",
"react-icons": "^4.11.0",
"react-redux": "^8.1.3",
+ "tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
+ },
+ "devDependencies": {
+ "@types/lodash": "^4.14.200"
}
}
diff --git a/public/images/hero-illo@3x.png b/public/images/hero-illo@3x.png
new file mode 100644
index 0000000..e303cff
Binary files /dev/null and b/public/images/hero-illo@3x.png differ
diff --git a/public/images/homepage-removebg.png b/public/images/homepage-removebg.png
new file mode 100644
index 0000000..378345c
Binary files /dev/null and b/public/images/homepage-removebg.png differ
diff --git a/public/images/homepage.png b/public/images/homepage.png
new file mode 100644
index 0000000..bca1640
Binary files /dev/null and b/public/images/homepage.png differ
diff --git a/redux/schedule/actions/discardChanges.ts b/redux/schedule/actions/discardChanges.ts
new file mode 100644
index 0000000..ff63594
--- /dev/null
+++ b/redux/schedule/actions/discardChanges.ts
@@ -0,0 +1,7 @@
+import { ScheduleState } from "../scheduleSlice";
+import { cloneDeep } from "lodash";
+
+export function discardChanges(state: ScheduleState) {
+ state.tempData = state.realData;
+ // state.editing = false;
+}
diff --git a/redux/schedule/actions/saveChanges.ts b/redux/schedule/actions/saveChanges.ts
new file mode 100644
index 0000000..7562cf1
--- /dev/null
+++ b/redux/schedule/actions/saveChanges.ts
@@ -0,0 +1,6 @@
+import { ScheduleState } from "../scheduleSlice";
+
+export function saveChanges(state: ScheduleState) {
+ state.realData = state.tempData;
+ state.editing = true;
+}
diff --git a/redux/schedule/actions/updateScheduleState.ts b/redux/schedule/actions/updateScheduleState.ts
new file mode 100644
index 0000000..efc9ec0
--- /dev/null
+++ b/redux/schedule/actions/updateScheduleState.ts
@@ -0,0 +1,10 @@
+import { ScheduleState } from '@/redux/schedule/scheduleSlice';
+import { ScheduleStyle } from '@/types/schedule';
+import { PayloadAction } from '@reduxjs/toolkit';
+
+export function updateScheduleState(state: ScheduleState, action: PayloadAction
>) {
+ return {
+ ...state,
+ ...action.payload
+ }
+}
diff --git a/redux/schedule/actions/updateScheduleStyle.ts b/redux/schedule/actions/updateScheduleStyle.ts
new file mode 100644
index 0000000..ad4f838
--- /dev/null
+++ b/redux/schedule/actions/updateScheduleStyle.ts
@@ -0,0 +1,11 @@
+import { ScheduleStyle } from "@/types/schedule";
+import { PayloadAction } from "@reduxjs/toolkit";
+import { ScheduleState } from "../scheduleSlice";
+
+export function updateScheduleStyle(state: ScheduleState, action: PayloadAction>) {
+ state.tempData.scheduleStyle = {
+ ...state.tempData.scheduleStyle,
+ ...action.payload
+ }
+ state.editing = true;
+}
diff --git a/redux/schedule/actions/updateScheduleSubjects.ts b/redux/schedule/actions/updateScheduleSubjects.ts
new file mode 100644
index 0000000..fb18aa1
--- /dev/null
+++ b/redux/schedule/actions/updateScheduleSubjects.ts
@@ -0,0 +1,29 @@
+import { PayloadAction } from "@reduxjs/toolkit"
+import { ScheduleState } from "../scheduleSlice"
+import { SubjectClass } from "@/types/subject"
+import { isUndefined } from "@/utils/isUndefined"
+
+export const updateScheduleSubjects = (state: ScheduleState, {
+ payload: {
+ index,
+ newProps
+ }
+}: PayloadAction<{
+ index: number
+ newProps: Partial
+}>) => {
+ state.tempData.subjectClassData[index] = {
+ ...state.tempData.subjectClassData[index],
+ ...newProps
+ }
+ let subjectClassData = state.tempData.subjectClassData;
+
+ if (!isUndefined(newProps.highlightColor)) {
+ subjectClassData.forEach((subjectClass, i) => {
+ if (i !== index && subjectClass.id === subjectClassData[index].id) {
+ subjectClassData[i].highlightColor = newProps.highlightColor as string
+ }
+ })
+ }
+ state.editing = true;
+}
diff --git a/redux/schedule/scheduleSelector.ts b/redux/schedule/scheduleSelector.ts
new file mode 100644
index 0000000..6f82d23
--- /dev/null
+++ b/redux/schedule/scheduleSelector.ts
@@ -0,0 +1,7 @@
+import { ScheduleInfo } from "@/types/schedule";
+import { RootState } from "../store";
+import { ScheduleState } from "./scheduleSlice";
+
+export const scheduleDataSelector = (state: RootState): ScheduleInfo => state.schedule.tempData;
+
+export const scheduleSelector = (state: RootState): ScheduleState => state.schedule
diff --git a/redux/schedule/scheduleSlice.ts b/redux/schedule/scheduleSlice.ts
new file mode 100644
index 0000000..e29468e
--- /dev/null
+++ b/redux/schedule/scheduleSlice.ts
@@ -0,0 +1,38 @@
+import { updateScheduleSubjects } from './actions/updateScheduleSubjects';
+import { createSlice } from "@reduxjs/toolkit";
+import { ScheduleInfo } from "@/types/schedule";
+import { getScheduleInfo } from "@/api/schedule";
+import { updateScheduleStyle } from "./actions/updateScheduleStyle";
+import { cloneDeep } from 'lodash';
+import { discardChanges } from './actions/discardChanges';
+import { saveChanges } from './actions/saveChanges';
+import { updateScheduleState } from './actions/updateScheduleState';
+
+export interface ScheduleState {
+ fetched: boolean
+ tempData: ScheduleInfo
+ realData: ScheduleInfo
+ editing: boolean
+}
+
+const initTempData: ScheduleInfo = getScheduleInfo(false);
+const initRealData: ScheduleInfo = cloneDeep(initTempData);
+
+const initialState: ScheduleState = {
+ fetched: true,
+ tempData: initTempData,
+ realData: initRealData,
+ editing: false
+}
+
+export const {reducer: scheduleReducer, actions: scheduleActions} = createSlice({
+ name: 'schedule',
+ initialState,
+ reducers: {
+ updateScheduleState,
+ updateScheduleStyle,
+ updateScheduleSubjects,
+ discardChanges,
+ saveChanges
+ }
+})
diff --git a/redux/store.ts b/redux/store.ts
index b66f3a8..b9cd6e8 100644
--- a/redux/store.ts
+++ b/redux/store.ts
@@ -1,9 +1,11 @@
import { configureStore } from "@reduxjs/toolkit";
import { authReducer } from "./auth/authSlice";
+import { scheduleReducer } from "./schedule/scheduleSlice";
export const store = configureStore({
reducer: {
- auth: authReducer
+ auth: authReducer,
+ schedule: scheduleReducer
}
});
diff --git a/styles/theme.ts b/styles/theme.ts
index f49473f..c1511de 100644
--- a/styles/theme.ts
+++ b/styles/theme.ts
@@ -8,5 +8,8 @@ export const THEME = {
LIGHT_PRIMARY_COLOR: '#c6e0f6',
SECONDARY_COLOR: '#FFFFFF',
ROYAL_GRAY_COLOR: '#7D7C7C',
+ TABLE_BORDER_COLOR: 'rgba(75, 85, 99)',
+ PRIMARY_ICON_COLOR: '#7D7C7C',
+ DANGER_COLOR: '#FF4D4F'
// MAIN_FONT: inter,
}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 060e3c5..361274f 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -2,6 +2,11 @@ import type { Config } from 'tailwindcss'
import { THEME } from './styles/theme'
const config: Config = {
+ // mode: 'jit',
+ // purge: [
+ // './public/**/*.html',
+ // './**/*.{js,jsx,ts,tsx,vue}',
+ // ],
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
@@ -22,6 +27,11 @@ const config: Config = {
"light-primary": THEME.LIGHT_PRIMARY_COLOR,
secondary: THEME.SECONDARY_COLOR,
"royal-gray": THEME.ROYAL_GRAY_COLOR,
+ 'table-border': THEME.TABLE_BORDER_COLOR,
+ 'danger': THEME.DANGER_COLOR
+ },
+ fontSize: {
+ 'fs-inherit': 'inherit'
}
},
},
diff --git a/types/schedule.ts b/types/schedule.ts
new file mode 100644
index 0000000..279b41c
--- /dev/null
+++ b/types/schedule.ts
@@ -0,0 +1,17 @@
+import { SubjectClass } from "./subject"
+
+export interface ScheduleStyle {
+ hasBorder: boolean
+ roundedBorder: boolean
+ lessonColumnColor: string
+ timeColumnColor: string
+ headerRowColor: string
+ dividerRowColor: string
+ hasDivider: boolean
+ displayColumnSettings: boolean
+}
+
+export interface ScheduleInfo {
+ subjectClassData: SubjectClass[]
+ scheduleStyle: ScheduleStyle
+}
diff --git a/types/subject.ts b/types/subject.ts
new file mode 100644
index 0000000..c16ac50
--- /dev/null
+++ b/types/subject.ts
@@ -0,0 +1,15 @@
+
+export interface SubjectClass {
+ id: string; ///
+ lessonStart: number;
+ lessonEnd: number;
+ group: string;
+ name: string;
+ place: string;
+ credits: number;
+ teacherName: string;
+ weekDay: number;
+ numberOfStudents: number;
+ highlightColor: string;
+ description?: string
+}
diff --git a/utils/isUndefined.ts b/utils/isUndefined.ts
new file mode 100644
index 0000000..342cbcc
--- /dev/null
+++ b/utils/isUndefined.ts
@@ -0,0 +1,3 @@
+export function isUndefined(value: any) {
+ return typeof value === 'undefined';
+}
diff --git a/utils/lightenDarkenColor.ts b/utils/lightenDarkenColor.ts
new file mode 100644
index 0000000..a29edec
--- /dev/null
+++ b/utils/lightenDarkenColor.ts
@@ -0,0 +1,6 @@
+// @ts-ignore
+import {LightenDarkenColor} from 'lighten-darken-color';
+
+export function lightenDarkenColor(color: string, amount: number): string {
+ return LightenDarkenColor(color, amount)
+}
diff --git a/utils/subjectClass.ts b/utils/subjectClass.ts
new file mode 100644
index 0000000..50019fb
--- /dev/null
+++ b/utils/subjectClass.ts
@@ -0,0 +1,63 @@
+import { SubjectClass } from "@/types/subject";
+import { time } from "console";
+import internal from "stream";
+
+/**
+ * thời gian còn lại tính từ hiện tại cho tới thời gian học của lớp đã cho tính bằng giây
+ * @param subjectClass thông tin về lớp
+ * @returns thời gian còn lại tính từ hiện tại cho tới thời gian học của lớp đó tính bằng giây
+ */
+
+export function nowToSubjectClass(subjectClass: SubjectClass): number {
+ const currentDate = new Date();
+ let currentWeekday = currentDate.getDay();
+ currentWeekday += (currentWeekday === 0 ? 8 : 1);
+
+ const targetDate = new Date(currentDate);
+ targetDate.setDate(currentDate.getDate() + subjectClass.weekDay - currentWeekday);
+ targetDate.setHours(lessonToHour(subjectClass.lessonStart), 0, 0, 0);
+
+ if (targetDate < currentDate)
+ targetDate.setDate(targetDate.getDate() + 7)
+
+ return (targetDate.getTime() - currentDate.getTime()) / 1000;
+};
+
+/**
+ *
+ * @param subjectClasses mảng các môn học
+ * @returns {
+ * time: Thời gian đến môn học gần nhất,
+ * subjectClass: môn học gần nhất,
+ * index: chỉ số môn học trong mảng
+ * } hoặc time = 0 và các trường khác undefined nếu mảng rỗng
+ */
+
+export function nowToNextSubjectClass(subjectClasses: SubjectClass[]): {
+ time: number
+ subjectClass: SubjectClass
+ index: number
+} {
+ if (subjectClasses.length === 0)
+ throw new Error('Hàm nowToNextSubjectClass có subjectClasses rỗng')
+ let mi: number = 0;
+ let minTime = nowToSubjectClass(subjectClasses[0]);
+
+ for (let i = 1; i < subjectClasses.length; ++i) {
+ let current = nowToSubjectClass(subjectClasses[i]);
+ if (minTime > current) {
+ minTime = current;
+ mi = i;
+ }
+ }
+
+ return {
+ time: minTime,
+ subjectClass: subjectClasses[mi],
+ index: mi
+ }
+}
+
+export function lessonToHour(lesson: number): number {
+ return lesson + 6;
+}