merging
This commit is contained in:
16
README.md
16
README.md
@@ -14,5 +14,17 @@
|
||||
|
||||
1. Clone this repo
|
||||
2. Run `pnpm install` to install and patch all the required dependencies
|
||||
3. Run `pnpm run dev` to start the development server
|
||||
4. Run `pnpm build` to build the extension for production
|
||||
|
||||
- If you want to run the development build:
|
||||
|
||||
- Run `pnpm run dev`
|
||||
|
||||
- If you want to build the extension for production:
|
||||
|
||||
- Run `pnpm build`
|
||||
|
||||
You may have to rename the `__uno.css.js` to `uno.css.js` in dist
|
||||
|
||||
Go to chrome://extensions, ensure you have "Developer Mode" enabled, and click 'Load unpacked'
|
||||
|
||||
Navigate to the 'dist' folder and click 'select' to import the extension
|
||||
|
||||
3258
package-lock.json
generated
3258
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,12 +26,14 @@
|
||||
"clsx": "^2.1.0",
|
||||
"highcharts": "^11.3.0",
|
||||
"highcharts-react-official": "^3.2.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"react": "^18.2.0",
|
||||
"react-devtools-core": "^5.0.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-window": "^1.8.10",
|
||||
"sass": "^1.70.0",
|
||||
"sql.js": "1.10.2",
|
||||
"styled-components": "^6.1.8",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
127
pnpm-lock.yaml
generated
127
pnpm-lock.yaml
generated
@@ -40,6 +40,9 @@ dependencies:
|
||||
highcharts-react-official:
|
||||
specifier: ^3.2.1
|
||||
version: 3.2.1(highcharts@11.3.0)(react@18.2.0)
|
||||
html2canvas:
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
@@ -58,6 +61,9 @@ dependencies:
|
||||
sql.js:
|
||||
specifier: 1.10.2
|
||||
version: 1.10.2
|
||||
styled-components:
|
||||
specifier: ^6.1.8
|
||||
version: 6.1.8(react-dom@18.2.0)(react@18.2.0)
|
||||
uuid:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
@@ -1735,6 +1741,20 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@emotion/is-prop-valid@1.2.1:
|
||||
resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.8.1
|
||||
dev: false
|
||||
|
||||
/@emotion/memoize@0.8.1:
|
||||
resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/unitless@0.8.0:
|
||||
resolution: {integrity: sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==}
|
||||
dev: false
|
||||
|
||||
/@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==}
|
||||
peerDependencies:
|
||||
@@ -4726,6 +4746,10 @@ packages:
|
||||
'@types/node': 20.11.17
|
||||
dev: false
|
||||
|
||||
/@types/stylis@4.2.0:
|
||||
resolution: {integrity: sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==}
|
||||
dev: false
|
||||
|
||||
/@types/trusted-types@2.0.7:
|
||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||
dev: true
|
||||
@@ -5878,6 +5902,11 @@ packages:
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
/base64-arraybuffer@1.0.2:
|
||||
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
dev: false
|
||||
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: true
|
||||
@@ -6118,6 +6147,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/camelize@1.0.1:
|
||||
resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
|
||||
dev: false
|
||||
|
||||
/caniuse-api@3.0.0:
|
||||
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
||||
dependencies:
|
||||
@@ -6562,6 +6595,11 @@ packages:
|
||||
tiny-invariant: 1.3.1
|
||||
dev: false
|
||||
|
||||
/css-color-keywords@1.0.0:
|
||||
resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/css-declaration-sorter@7.1.1(postcss@8.4.35):
|
||||
resolution: {integrity: sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==}
|
||||
engines: {node: ^14 || ^16 || >=18}
|
||||
@@ -6571,6 +6609,12 @@ packages:
|
||||
postcss: 8.4.35
|
||||
dev: true
|
||||
|
||||
/css-line-break@2.1.0:
|
||||
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
dev: false
|
||||
|
||||
/css-select@5.1.0:
|
||||
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
|
||||
dependencies:
|
||||
@@ -6581,6 +6625,14 @@ packages:
|
||||
nth-check: 2.1.1
|
||||
dev: true
|
||||
|
||||
/css-to-react-native@3.2.0:
|
||||
resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==}
|
||||
dependencies:
|
||||
camelize: 1.0.1
|
||||
css-color-keywords: 1.0.0
|
||||
postcss-value-parser: 4.2.0
|
||||
dev: false
|
||||
|
||||
/css-tree@2.2.1:
|
||||
resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
|
||||
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||
@@ -6691,6 +6743,10 @@ packages:
|
||||
css-tree: 2.2.1
|
||||
dev: true
|
||||
|
||||
/csstype@3.1.2:
|
||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
||||
dev: false
|
||||
|
||||
/csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
@@ -8660,6 +8716,14 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/html2canvas@1.4.1:
|
||||
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
dependencies:
|
||||
css-line-break: 2.1.0
|
||||
text-segmentation: 1.0.3
|
||||
dev: false
|
||||
|
||||
/htmlparser2@8.0.2:
|
||||
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
|
||||
dependencies:
|
||||
@@ -10900,6 +10964,15 @@ packages:
|
||||
postcss: 8.4.35
|
||||
dev: true
|
||||
|
||||
/postcss@8.4.31:
|
||||
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
dependencies:
|
||||
nanoid: 3.3.7
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
dev: false
|
||||
|
||||
/postcss@8.4.35:
|
||||
resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -11891,6 +11964,10 @@ packages:
|
||||
kind-of: 6.0.3
|
||||
dev: true
|
||||
|
||||
/shallowequal@1.1.0:
|
||||
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
||||
dev: false
|
||||
|
||||
/shebang-command@1.2.0:
|
||||
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -12225,6 +12302,26 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/styled-components@6.1.8(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==}
|
||||
engines: {node: '>= 16'}
|
||||
peerDependencies:
|
||||
react: '>= 16.8.0'
|
||||
react-dom: '>= 16.8.0'
|
||||
dependencies:
|
||||
'@emotion/is-prop-valid': 1.2.1
|
||||
'@emotion/unitless': 0.8.0
|
||||
'@types/stylis': 4.2.0
|
||||
css-to-react-native: 3.2.0
|
||||
csstype: 3.1.2
|
||||
postcss: 8.4.31
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
shallowequal: 1.1.0
|
||||
stylis: 4.3.1
|
||||
tslib: 2.5.0
|
||||
dev: false
|
||||
|
||||
/stylehacks@6.0.2(postcss@8.4.35):
|
||||
resolution: {integrity: sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==}
|
||||
engines: {node: ^14 || ^16 || >=18.0}
|
||||
@@ -12236,18 +12333,8 @@ packages:
|
||||
postcss-selector-parser: 6.0.15
|
||||
dev: true
|
||||
|
||||
/sucrase@3.35.0:
|
||||
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
commander: 4.1.1
|
||||
glob: 10.3.10
|
||||
lines-and-columns: 1.2.4
|
||||
mz: 2.7.0
|
||||
pirates: 4.0.6
|
||||
ts-interface-checker: 0.1.13
|
||||
/stylis@4.3.1:
|
||||
resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==}
|
||||
dev: false
|
||||
|
||||
/sumchecker@3.0.1:
|
||||
@@ -12475,6 +12562,12 @@ packages:
|
||||
minimatch: 3.1.2
|
||||
dev: true
|
||||
|
||||
/text-segmentation@1.0.3:
|
||||
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
dev: false
|
||||
|
||||
/text-table@0.2.0:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
dev: true
|
||||
@@ -12580,6 +12673,10 @@ packages:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
||||
/tslib@2.5.0:
|
||||
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
|
||||
dev: false
|
||||
|
||||
/tslib@2.6.2:
|
||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
||||
dev: true
|
||||
@@ -13029,6 +13126,12 @@ packages:
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dev: true
|
||||
|
||||
/utrie@1.0.2:
|
||||
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
|
||||
dependencies:
|
||||
base64-arraybuffer: 1.0.2
|
||||
dev: false
|
||||
|
||||
/uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
|
||||
8
src/assets/icons/cal.svg
Normal file
8
src/assets/icons/cal.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_3175_7842" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="25">
|
||||
<rect y="0.5" width="24" height="24" fill="#D9D9D9"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_3175_7842)">
|
||||
<path d="M12 14.5C11.7167 14.5 11.4792 14.4042 11.2875 14.2125C11.0958 14.0208 11 13.7833 11 13.5C11 13.2167 11.0958 12.9792 11.2875 12.7875C11.4792 12.5958 11.7167 12.5 12 12.5C12.2833 12.5 12.5208 12.5958 12.7125 12.7875C12.9042 12.9792 13 13.2167 13 13.5C13 13.7833 12.9042 14.0208 12.7125 14.2125C12.5208 14.4042 12.2833 14.5 12 14.5ZM8 14.5C7.71667 14.5 7.47917 14.4042 7.2875 14.2125C7.09583 14.0208 7 13.7833 7 13.5C7 13.2167 7.09583 12.9792 7.2875 12.7875C7.47917 12.5958 7.71667 12.5 8 12.5C8.28333 12.5 8.52083 12.5958 8.7125 12.7875C8.90417 12.9792 9 13.2167 9 13.5C9 13.7833 8.90417 14.0208 8.7125 14.2125C8.52083 14.4042 8.28333 14.5 8 14.5ZM16 14.5C15.7167 14.5 15.4792 14.4042 15.2875 14.2125C15.0958 14.0208 15 13.7833 15 13.5C15 13.2167 15.0958 12.9792 15.2875 12.7875C15.4792 12.5958 15.7167 12.5 16 12.5C16.2833 12.5 16.5208 12.5958 16.7125 12.7875C16.9042 12.9792 17 13.2167 17 13.5C17 13.7833 16.9042 14.0208 16.7125 14.2125C16.5208 14.4042 16.2833 14.5 16 14.5ZM12 18.5C11.7167 18.5 11.4792 18.4042 11.2875 18.2125C11.0958 18.0208 11 17.7833 11 17.5C11 17.2167 11.0958 16.9792 11.2875 16.7875C11.4792 16.5958 11.7167 16.5 12 16.5C12.2833 16.5 12.5208 16.5958 12.7125 16.7875C12.9042 16.9792 13 17.2167 13 17.5C13 17.7833 12.9042 18.0208 12.7125 18.2125C12.5208 18.4042 12.2833 18.5 12 18.5ZM8 18.5C7.71667 18.5 7.47917 18.4042 7.2875 18.2125C7.09583 18.0208 7 17.7833 7 17.5C7 17.2167 7.09583 16.9792 7.2875 16.7875C7.47917 16.5958 7.71667 16.5 8 16.5C8.28333 16.5 8.52083 16.5958 8.7125 16.7875C8.90417 16.9792 9 17.2167 9 17.5C9 17.7833 8.90417 18.0208 8.7125 18.2125C8.52083 18.4042 8.28333 18.5 8 18.5ZM16 18.5C15.7167 18.5 15.4792 18.4042 15.2875 18.2125C15.0958 18.0208 15 17.7833 15 17.5C15 17.2167 15.0958 16.9792 15.2875 16.7875C15.4792 16.5958 15.7167 16.5 16 16.5C16.2833 16.5 16.5208 16.5958 16.7125 16.7875C16.9042 16.9792 17 17.2167 17 17.5C17 17.7833 16.9042 18.0208 16.7125 18.2125C16.5208 18.4042 16.2833 18.5 16 18.5ZM5 22.5C4.45 22.5 3.97917 22.3042 3.5875 21.9125C3.19583 21.5208 3 21.05 3 20.5V6.5C3 5.95 3.19583 5.47917 3.5875 5.0875C3.97917 4.69583 4.45 4.5 5 4.5H6V2.5H8V4.5H16V2.5H18V4.5H19C19.55 4.5 20.0208 4.69583 20.4125 5.0875C20.8042 5.47917 21 5.95 21 6.5V20.5C21 21.05 20.8042 21.5208 20.4125 21.9125C20.0208 22.3042 19.55 22.5 19 22.5H5ZM5 20.5H19V10.5H5V20.5Z" fill="#333F48"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
8
src/assets/icons/png.svg
Normal file
8
src/assets/icons/png.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_3211_5369" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="25">
|
||||
<rect y="0.5" width="24" height="24" fill="#D9D9D9"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_3211_5369)">
|
||||
<path d="M5 21.5C4.45 21.5 3.97917 21.3042 3.5875 20.9125C3.19583 20.5208 3 20.05 3 19.5V5.5C3 4.95 3.19583 4.47917 3.5875 4.0875C3.97917 3.69583 4.45 3.5 5 3.5H19C19.55 3.5 20.0208 3.69583 20.4125 4.0875C20.8042 4.47917 21 4.95 21 5.5V19.5C21 20.05 20.8042 20.5208 20.4125 20.9125C20.0208 21.3042 19.55 21.5 19 21.5H5ZM6 17.5H18L14.25 12.5L11.25 16.5L9 13.5L6 17.5Z" fill="#333F48"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 702 B |
101
src/stories/components/CalendarBottomBar.stories.tsx
Normal file
101
src/stories/components/CalendarBottomBar.stories.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { Course, Status } from '@shared/types/Course';
|
||||
import Instructor from '@shared/types/Instructor';
|
||||
import { CalendarBottomBar } from '@views/components/common/CalendarBottomBar/CalendarBottomBar';
|
||||
import { getCourseColors } from '../../shared/util/colors';
|
||||
|
||||
const exampleGovCourse: Course = new Course({
|
||||
courseName: 'Nope',
|
||||
creditHours: 3,
|
||||
department: 'GOV',
|
||||
description: ['nah', 'aint typing this', 'corndog'],
|
||||
flags: ['no flag for you >:)'],
|
||||
fullName: 'GOV 312L Something something',
|
||||
instructionMode: 'Online',
|
||||
instructors: [
|
||||
new Instructor({
|
||||
firstName: 'Bevo',
|
||||
lastName: 'Barrymore',
|
||||
fullName: 'Bevo Barrymore',
|
||||
}),
|
||||
],
|
||||
isReserved: false,
|
||||
number: '312L',
|
||||
schedule: {
|
||||
meetings: [],
|
||||
},
|
||||
semester: {
|
||||
code: '12345',
|
||||
season: 'Spring',
|
||||
year: 2024,
|
||||
},
|
||||
status: Status.OPEN,
|
||||
uniqueId: 12345,
|
||||
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
|
||||
});
|
||||
|
||||
const examplePsyCourse: Course = new Course({
|
||||
courseName: 'Nope Again',
|
||||
creditHours: 3,
|
||||
department: 'PSY',
|
||||
description: ['nah', 'aint typing this', 'corndog'],
|
||||
flags: ['no flag for you >:)'],
|
||||
fullName: 'PSY 317L Yada yada',
|
||||
instructionMode: 'Online',
|
||||
instructors: [
|
||||
new Instructor({
|
||||
firstName: 'Bevo',
|
||||
lastName: 'Etz',
|
||||
fullName: 'Bevo Etz',
|
||||
}),
|
||||
],
|
||||
isReserved: false,
|
||||
number: '317L',
|
||||
schedule: {
|
||||
meetings: [],
|
||||
},
|
||||
semester: {
|
||||
code: '12346',
|
||||
season: 'Spring',
|
||||
year: 2024,
|
||||
},
|
||||
status: Status.CLOSED,
|
||||
uniqueId: 12346,
|
||||
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
|
||||
});
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Common/CalendarBottomBar',
|
||||
component: CalendarBottomBar,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {},
|
||||
} satisfies Meta<typeof CalendarBottomBar>;
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
courses: [
|
||||
{
|
||||
colors: getCourseColors('pink', 200),
|
||||
courseDeptAndInstr: `${exampleGovCourse.department} ${exampleGovCourse.number} – ${exampleGovCourse.instructors[0].lastName}`,
|
||||
status: exampleGovCourse.status,
|
||||
},
|
||||
{
|
||||
colors: getCourseColors('slate', 500),
|
||||
courseDeptAndInstr: `${examplePsyCourse.department} ${examplePsyCourse.number} – ${examplePsyCourse.instructors[0].lastName}`,
|
||||
status: examplePsyCourse.status,
|
||||
},
|
||||
],
|
||||
},
|
||||
render: props => (
|
||||
<div className='outline-red outline w-292.5!'>
|
||||
<CalendarBottomBar {...props} />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
@@ -30,8 +30,7 @@ const meta = {
|
||||
courseNumber: exampleCourse.number,
|
||||
instructorLastName: exampleCourse.instructors[0].lastName,
|
||||
status: exampleCourse.status,
|
||||
meetingTime: exampleCourse.schedule.meetings[0].getTimeString({separator: '-'}),
|
||||
|
||||
meetingTime: exampleCourse.schedule.meetings[0].getTimeString({ separator: '-' }),
|
||||
|
||||
colors: getCourseColors('emerald', 500),
|
||||
},
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import CalendarGrid from 'src/views/components/common/CalendarGrid/CalendarGrid';
|
||||
import { getCourseColors } from 'src/shared/util/colors';
|
||||
import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule';
|
||||
import { Status } from 'src/shared/types/Course';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Common/CalendarGrid',
|
||||
@@ -14,10 +17,41 @@ const meta = {
|
||||
} satisfies Meta<typeof CalendarGrid>;
|
||||
export default meta;
|
||||
|
||||
const testData: CalendarGridCourse[] = [
|
||||
{
|
||||
calendarGridPoint: {
|
||||
dayIndex: 0,
|
||||
startIndex: 1,
|
||||
endIndex: 2,
|
||||
},
|
||||
componentProps: {
|
||||
courseDeptAndInstr: 'Course 1',
|
||||
timeAndLocation: '9:00 AM - 10:00 AM, Room 101',
|
||||
status: Status.OPEN,
|
||||
colors: getCourseColors('emerald', 500),
|
||||
},
|
||||
},
|
||||
{
|
||||
calendarGridPoint: {
|
||||
dayIndex: 1,
|
||||
startIndex: 2,
|
||||
endIndex: 3,
|
||||
},
|
||||
componentProps: {
|
||||
courseDeptAndInstr: 'Course 2',
|
||||
timeAndLocation: '10:00 AM - 11:00 AM, Room 102',
|
||||
status: Status.CLOSED,
|
||||
colors: getCourseColors('emerald', 500),
|
||||
},
|
||||
},
|
||||
// add more data as needed
|
||||
];
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
saturdayClass: true,
|
||||
courseCells: testData,
|
||||
},
|
||||
};
|
||||
@@ -3,7 +3,7 @@ import { Meta, StoryObj } from '@storybook/react';
|
||||
import CalendarHeader from '@views/components/common/CalendarHeader/CalenderHeader';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/CalendarHeader',
|
||||
title: 'Components/Common/CalendarHeader',
|
||||
component: CalendarHeader,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function ImportantLinks({ className }: Props) {
|
||||
<Text variant='h3'>Important Links</Text>
|
||||
<a
|
||||
href='https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/'
|
||||
className='text-ut-burntorange flex items-center gap-0.5'
|
||||
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
@@ -26,7 +26,7 @@ export default function ImportantLinks({ className }: Props) {
|
||||
</a>
|
||||
<a
|
||||
href='https://utdirect.utexas.edu/apps/registrar/course_schedule/20236/'
|
||||
className='text-ut-burntorange flex items-center gap-0.5'
|
||||
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
@@ -35,7 +35,7 @@ export default function ImportantLinks({ className }: Props) {
|
||||
</a>
|
||||
<a
|
||||
href='https://utdirect.utexas.edu/registrar/ris.WBX'
|
||||
className='text-ut-burntorange flex items-center gap-0.5'
|
||||
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
@@ -44,7 +44,7 @@ export default function ImportantLinks({ className }: Props) {
|
||||
</a>
|
||||
<a
|
||||
href='https://utdirect.utexas.edu/registration/chooseSemester.WBX'
|
||||
className='text-ut-burntorange flex items-center gap-0.5'
|
||||
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
@@ -53,7 +53,7 @@ export default function ImportantLinks({ className }: Props) {
|
||||
</a>
|
||||
<a
|
||||
href='https://utdirect.utexas.edu/apps/degree/audits/'
|
||||
className='text-ut-burntorange flex items-center gap-0.5'
|
||||
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Text from '../Text/Text';
|
||||
import CalendarCourseBlock, { CalendarCourseCellProps } from '../CalendarCourseCell/CalendarCourseCell';
|
||||
import { Button } from '../Button/Button';
|
||||
import ImageIcon from '~icons/material-symbols/image';
|
||||
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
|
||||
|
||||
type CalendarBottomBarProps = {
|
||||
courses: CalendarCourseCellProps[];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const CalendarBottomBar = ({ courses }: CalendarBottomBarProps): JSX.Element => {
|
||||
if (courses.length === -1) console.log('foo'); // dumb line to make eslint happy
|
||||
return (
|
||||
<div className='w-full flex py-1.25'>
|
||||
<div className='flex flex-grow items-center gap-3.75 pl-7.5 pr-2.5'>
|
||||
<Text variant='h4'>Async. and Other:</Text>
|
||||
<div className='h-14 inline-flex gap-2.5'>
|
||||
{courses.map(course => (
|
||||
<CalendarCourseBlock
|
||||
courseDeptAndInstr={course.courseDeptAndInstr}
|
||||
status={course.status}
|
||||
colors={course.colors}
|
||||
key={course.courseDeptAndInstr}
|
||||
className={clsx(course.className, 'w-35!')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-center pl-2.5 pr-7.5'>
|
||||
<Button variant='single' color='ut-black' icon={CalendarMonthIcon}>
|
||||
Save as .CAL
|
||||
</Button>
|
||||
<Button variant='single' color='ut-black' icon={ImageIcon}>
|
||||
Save as .PNG
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -12,6 +12,7 @@ export interface CalendarCourseCellProps {
|
||||
timeAndLocation?: string;
|
||||
status: Status;
|
||||
colors: CourseColors;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
||||
@@ -19,6 +20,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
||||
timeAndLocation,
|
||||
status,
|
||||
colors,
|
||||
className,
|
||||
}: CalendarCourseCellProps) => {
|
||||
let rightIcon: React.ReactNode | null = null;
|
||||
if (status === Status.WAITLISTED) {
|
||||
@@ -34,7 +36,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full flex justify-center rounded p-2 ${fontColor}`}
|
||||
className={clsx('w-full flex justify-center rounded p-2', fontColor, className)}
|
||||
style={{
|
||||
backgroundColor: colors.primaryColor,
|
||||
}}
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
}
|
||||
|
||||
.calendar {
|
||||
// display: grid;
|
||||
// grid-template-columns: auto repeat(5, 1fr);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
position: relative; // Ensuring that child elements can be positioned in relation to this.
|
||||
}
|
||||
|
||||
.day {
|
||||
@@ -89,3 +90,38 @@
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.calendarButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 6px 6px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.buttonIcon {
|
||||
height: 24px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 30px;
|
||||
width: 1px;
|
||||
background-color: grey;
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
import React from 'react';
|
||||
import React, { useRef } from 'react';
|
||||
import html2canvas from 'html2canvas';
|
||||
import { DAY_MAP } from 'src/shared/types/CourseMeeting';
|
||||
import styles from './CalendarGrid.module.scss';
|
||||
import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule';
|
||||
import calIcon from 'src/assets/icons/cal.svg';
|
||||
import pngIcon from 'src/assets/icons/png.svg';
|
||||
import CalendarCell from '../CalendarGridCell/CalendarGridCell';
|
||||
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
|
||||
import { Chip } from '../Chip/Chip';
|
||||
import styles from './CalendarGrid.module.scss';
|
||||
|
||||
const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
|
||||
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
|
||||
@@ -23,7 +26,7 @@ for (let i = 0; i < 13; i++) {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
courseCells: any[];
|
||||
courseCells: CalendarGridCourse[];
|
||||
saturdayClass: boolean;
|
||||
}
|
||||
|
||||
@@ -31,12 +34,26 @@ interface Props {
|
||||
* Grid of CalendarGridCell components forming the user's course schedule calendar view
|
||||
* @param props
|
||||
*/
|
||||
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props> ): JSX.Element {
|
||||
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element {
|
||||
const calendarRef = useRef(null); // Create a ref for the calendar grid
|
||||
|
||||
const saveAsPNG = () => {
|
||||
if (calendarRef.current) {
|
||||
html2canvas(calendarRef.current).then(canvas => {
|
||||
// Create an a element to trigger download
|
||||
const a = document.createElement('a');
|
||||
a.href = canvas.toDataURL('image/png');
|
||||
a.download = 'calendar.png';
|
||||
a.click();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.calendar}>
|
||||
<div className={styles.dayLabelContainer} />
|
||||
{/* Displaying the rest of the calendar */}
|
||||
<div className={styles.timeAndGrid}>
|
||||
<div ref={calendarRef} className={styles.timeAndGrid}>
|
||||
{/* <div className={styles.timeColumn}>
|
||||
<div className={styles.timeBlock}></div>
|
||||
{hoursOfDay.map((hour) => (
|
||||
@@ -55,20 +72,38 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
|
||||
{day}
|
||||
</div>
|
||||
))}
|
||||
{grid.map(row => row)}
|
||||
{grid.map((row, index) => (
|
||||
<React.Fragment key={index}>{row}</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* courseCells.map((Block: typeof CalendarCourseCell) => (
|
||||
{courseCells.map((block: CalendarGridCourse) => (
|
||||
<div
|
||||
key={`${Block}`}
|
||||
key={`${block}`}
|
||||
style={{
|
||||
gridColumn: `1`,
|
||||
gridRow: `1`,
|
||||
gridColumn: `${block.calendarGridPoint.dayIndex}`,
|
||||
gridRow: `${block.calendarGridPoint.startIndex} / ${block.calendarGridPoint.endIndex}`,
|
||||
}}
|
||||
>
|
||||
<Chip label='test' />
|
||||
<CalendarCourseCell
|
||||
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
|
||||
status={block.componentProps.status}
|
||||
colors={block.componentProps.colors}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className={styles.buttonContainer}>
|
||||
<div className={styles.divider} /> {/* First divider */}
|
||||
<button className={styles.calendarButton}>
|
||||
<img src={calIcon} className={styles.buttonIcon} alt='CAL' />
|
||||
Save as .CAL
|
||||
</button>
|
||||
<div className={styles.divider} /> {/* Second divider */}
|
||||
<button onClick={saveAsPNG} className={styles.calendarButton}>
|
||||
<img src={pngIcon} className={styles.buttonIcon} alt='PNG' />
|
||||
Save as .PNG
|
||||
</button>
|
||||
</div>
|
||||
)) */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,40 +12,41 @@ import ScheduleTotalHoursAndCourses from '../ScheduleTotalHoursAndCourses/Schedu
|
||||
import CourseStatus from '../CourseStatus/CourseStatus';
|
||||
|
||||
const CalendarHeader = () => (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
minWidth: '672px',
|
||||
minHeight: '79px',
|
||||
padding: '15px 0px',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
alignContent: 'center',
|
||||
rowGap: '10px',
|
||||
alignSelf: 'stretch',
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
<div className='min-h-79px min-w-672px flex px-0 py-15'>
|
||||
<div className='flex flex-row gap-20'>
|
||||
<div className='flex gap-10'>
|
||||
<div className='flex gap-1'>
|
||||
<Button variant='single' icon={MenuIcon} color='ut-gray' />
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<div className='flex items-center'>
|
||||
<LogoIcon style={{ marginRight: '5px' }} />
|
||||
<Text>Your Logo Text</Text>
|
||||
<div className='flex flex-col gap-1 whitespace-nowrap'>
|
||||
<Text className='leading-trim text-cap font-roboto text-base text-ut-burntorange font-medium'>
|
||||
UT Registration
|
||||
</Text>
|
||||
<Text className='leading-trim text-cap font-roboto text-base text-ut-orange font-medium'>
|
||||
Plus
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-col'>
|
||||
<ScheduleTotalHoursAndCourses scheduleName='SCHEDULE' totalHours={22} totalCourses={8} />
|
||||
|
||||
DATA UPDATED ON: 12:00 AM 02/01/2024
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-row items-center space-x-8'>
|
||||
<div className='flex flex-row space-x-4'>
|
||||
<CourseStatus size='small' status={Status.WAITLISTED} />
|
||||
<CourseStatus size='small' status={Status.CLOSED} />
|
||||
<CourseStatus size='small' status={Status.CANCELLED} />
|
||||
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Button variant='outline' icon={UndoIcon} color='ut-black' />
|
||||
<Button variant='outline' icon={RedoIcon} color='ut-black' />
|
||||
</div>
|
||||
|
||||
<Button variant='outline' icon={SettingsIcon} color='ut-black' />
|
||||
|
||||
<div className='flex flex-row'>
|
||||
<Button variant='single' icon={UndoIcon} color='ut-black' />
|
||||
<Button variant='single' icon={RedoIcon} color='ut-black' />
|
||||
<Button variant='single' icon={SettingsIcon} color='ut-black' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Divider type='solid' />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function ScheduleTotalHoursAndCourses({
|
||||
totalCourses,
|
||||
}: ScheduleTotalHoursAndCoursesProps): JSX.Element {
|
||||
return (
|
||||
<div className='min-w-64 flex flex-wrap content-center items-baseline gap-2 uppercase'>
|
||||
<div className='min-w-64 flex whitespace-nowrap content-center items-baseline gap-2 uppercase'>
|
||||
<Text className='text-[#BF5700]' variant='h1' as='span'>
|
||||
{`${scheduleName}: `}
|
||||
</Text>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CalendarCourseCellProps } from 'src/views/components/common/CalendarCourseCell/CalendarCourseCell';
|
||||
import useSchedules from './useSchedules';
|
||||
|
||||
const dayToNumber = {
|
||||
const dayToNumber: { [day: string]: number } = {
|
||||
Monday: 0,
|
||||
Tuesday: 1,
|
||||
Wednesday: 2,
|
||||
@@ -15,18 +15,26 @@ interface CalendarGridPoint {
|
||||
endIndex: number;
|
||||
}
|
||||
|
||||
interface SomeObject {
|
||||
calendarGridPoint?: CalendarGridPoint;
|
||||
/**
|
||||
* Return type of useFlattenedCourseSchedule
|
||||
*/
|
||||
export interface CalendarGridCourse {
|
||||
calendarGridPoint: CalendarGridPoint;
|
||||
componentProps: CalendarCourseCellProps;
|
||||
}
|
||||
|
||||
const convertMinutesToIndex = (minutes: number): number => Math.floor(minutes - 420 / 30);
|
||||
|
||||
export function useFlattenedCourseSchedule() {
|
||||
/**
|
||||
* Get the active schedule, and convert it to be render-able into a calendar.
|
||||
* @returns CalendarGridCourse
|
||||
*/
|
||||
export function useFlattenedCourseSchedule(): CalendarGridCourse[] {
|
||||
const [activeSchedule] = useSchedules();
|
||||
const { courses } = activeSchedule;
|
||||
|
||||
const out = courses.flatMap(course => {
|
||||
return courses
|
||||
.flatMap(course => {
|
||||
const {
|
||||
status,
|
||||
department,
|
||||
@@ -39,10 +47,16 @@ export function useFlattenedCourseSchedule() {
|
||||
// asynch, online course
|
||||
return [
|
||||
{
|
||||
calendarGridPoint: {
|
||||
dayIndex: 0,
|
||||
startIndex: 0,
|
||||
endIndex: 0,
|
||||
},
|
||||
componentProps: {
|
||||
courseDeptAndInstr,
|
||||
status,
|
||||
colors: {
|
||||
// TODO: figure out colors - these are defaults
|
||||
primaryColor: 'ut-gray',
|
||||
secondaryColor: 'ut-gray',
|
||||
},
|
||||
@@ -50,36 +64,39 @@ export function useFlattenedCourseSchedule() {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// in-person
|
||||
return meetings.flatMap(meeting => {
|
||||
const { days, startTime, endTime, location } = meeting;
|
||||
const time = meeting.getTimeString({ separator: ' - ', capitalize: true });
|
||||
const time = meeting.getTimeString({ separator: '-', capitalize: true });
|
||||
const timeAndLocation = `${time} - ${location ? location.building : 'WB'}`;
|
||||
|
||||
return days.map(d => {
|
||||
const dayIndex = dayToNumber[d];
|
||||
const startIndex = convertMinutesToIndex(startTime);
|
||||
const endIndex = convertMinutesToIndex(endTime);
|
||||
const calendarGridPoint: CalendarGridPoint = {
|
||||
dayIndex,
|
||||
startIndex,
|
||||
endIndex,
|
||||
};
|
||||
|
||||
return {
|
||||
calendarGridPoint,
|
||||
return days.map(d => ({
|
||||
calendarGridPoint: {
|
||||
dayIndex: dayToNumber[d],
|
||||
startIndex: convertMinutesToIndex(startTime),
|
||||
endIndex: convertMinutesToIndex(endTime),
|
||||
},
|
||||
componentProps: {
|
||||
courseDeptAndInstr,
|
||||
timeAndLocation,
|
||||
status,
|
||||
colors: {
|
||||
// TODO: figure out colors - these are defaults
|
||||
primaryColor: 'ut-orange',
|
||||
secondaryColor: 'ut-orange',
|
||||
},
|
||||
},
|
||||
};
|
||||
}));
|
||||
});
|
||||
})
|
||||
.sort((a: CalendarGridCourse, b: CalendarGridCourse) => {
|
||||
if (a.calendarGridPoint.dayIndex !== b.calendarGridPoint.dayIndex) {
|
||||
return a.calendarGridPoint.dayIndex - b.calendarGridPoint.dayIndex;
|
||||
}
|
||||
if (a.calendarGridPoint.startIndex !== b.calendarGridPoint.startIndex) {
|
||||
return a.calendarGridPoint.startIndex - b.calendarGridPoint.startIndex;
|
||||
}
|
||||
return a.calendarGridPoint.endIndex - b.calendarGridPoint.endIndex;
|
||||
});
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user