toggle switches
This commit is contained in:
parent
f276a6276e
commit
aa820d4910
12 changed files with 396 additions and 58 deletions
35
lib/queries.ts
Normal file
35
lib/queries.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { format } from "date-fns";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
type JournalQueryDate = JournalEntry[];
|
||||
|
||||
interface JournalEntry {
|
||||
"journal-day": number;
|
||||
"original-name": string;
|
||||
}
|
||||
|
||||
export function useJournals(dateStart: Date, dateEnd: Date) {
|
||||
const fmtStart = journalFmt(dateStart);
|
||||
const fmtEnd = journalFmt(dateEnd);
|
||||
|
||||
return useQuery(["journals", dateStart, dateEnd], async () => {
|
||||
const journals: JournalQueryDate[] = await logseq.DB.datascriptQuery(`
|
||||
[:find (pull ?p [*])
|
||||
:where
|
||||
[?b :block/page ?p]
|
||||
[?p :block/journal? true]
|
||||
[?p :block/journal-day ?d]
|
||||
[(>= ?d ${fmtStart})] [(<= ?d ${fmtEnd})]]
|
||||
`);
|
||||
|
||||
return new Map(
|
||||
journals
|
||||
.flatMap((dates) => dates)
|
||||
.map((entry) => [entry["journal-day"].toString(), entry])
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function journalFmt(date: Date) {
|
||||
return format(date, "YMMdd");
|
||||
}
|
203
package-lock.json
generated
203
package-lock.json
generated
|
@ -13,7 +13,8 @@
|
|||
"date-fns": "^2.30.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-keybind": "^0.9.4"
|
||||
"react-keybind": "^0.9.4",
|
||||
"react-query": "^3.39.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@logseq/libs": "^0.0.1-alpha.29",
|
||||
|
@ -868,6 +869,19 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
|
@ -877,6 +891,15 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
|
@ -889,6 +912,21 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/broadcast-channel": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
|
||||
"integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.2",
|
||||
"detect-node": "^2.1.0",
|
||||
"js-sha3": "0.8.0",
|
||||
"microseconds": "0.2.0",
|
||||
"nano-time": "1.0.0",
|
||||
"oblivious-set": "1.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
"unload": "2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.10",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
|
||||
|
@ -1002,6 +1040,11 @@
|
|||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
|
@ -1046,6 +1089,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
||||
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz",
|
||||
|
@ -1147,6 +1195,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
@ -1170,6 +1223,25 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
|
@ -1212,11 +1284,19 @@
|
|||
"integrity": "sha512-808ZFYMsIRAjLAu5xkKo0TsbY9LBy9H5MazTKIEHerNkg0ymgilGfBPMR/3G7d/ihGmuK2Hw8S1izY2d3kd3wA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
|
@ -1260,6 +1340,11 @@
|
|||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -1324,12 +1409,45 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/match-sorter": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz",
|
||||
"integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"remove-accents": "0.4.2"
|
||||
}
|
||||
},
|
||||
"node_modules/microseconds": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
|
||||
"integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA=="
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nano-time": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
|
||||
"integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.16"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
|
@ -1373,6 +1491,19 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/oblivious-set": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
|
||||
"integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw=="
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/path": {
|
||||
"version": "0.12.7",
|
||||
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
|
||||
|
@ -1383,6 +1514,14 @@
|
|||
"util": "^0.10.3"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
@ -1466,6 +1605,31 @@
|
|||
"resolved": "https://registry.npmjs.org/react-keybind/-/react-keybind-0.9.4.tgz",
|
||||
"integrity": "sha512-JVlXJ4ONQFQtEDZqXpc5NZ3oLEJtj7lKCPMLsbAO6FfkXJ21VHKyDtiLUIMio3d3oSC8QfxDOQtUEeVrMW6HfQ=="
|
||||
},
|
||||
"node_modules/react-query": {
|
||||
"version": "3.39.3",
|
||||
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
|
||||
"integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"broadcast-channel": "^3.4.1",
|
||||
"match-sorter": "^6.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
|
@ -1492,6 +1656,25 @@
|
|||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
|
||||
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
|
||||
},
|
||||
"node_modules/remove-accents": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
|
||||
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "3.28.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
|
||||
|
@ -1633,6 +1816,15 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unload": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
|
||||
"integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"detect-node": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
|
||||
|
@ -1746,6 +1938,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"date-fns": "^2.30.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-keybind": "^0.9.4"
|
||||
"react-keybind": "^0.9.4",
|
||||
"react-query": "^3.39.3"
|
||||
}
|
||||
}
|
||||
|
|
22
randomshit.txt
Normal file
22
randomshit.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
const monthColors = [
|
||||
"#AA3939",
|
||||
"#FFAAAA",
|
||||
"#D46A6A",
|
||||
"#801515",
|
||||
"#550000",
|
||||
"#AA6C39",
|
||||
"#FFD1AA",
|
||||
"#D49A6A",
|
||||
"#804515",
|
||||
"#552700",
|
||||
"#226666",
|
||||
"#669999",
|
||||
"#407F7F",
|
||||
"#0D4D4D",
|
||||
"#003333",
|
||||
"#2D882D",
|
||||
"#88CC88",
|
||||
"#55AA55",
|
||||
"#116611",
|
||||
"#004400",
|
||||
];
|
|
@ -9,4 +9,8 @@ main.app {
|
|||
|
||||
.header {
|
||||
padding-top: 40px;
|
||||
flex-basis: 120px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
23
src/App.tsx
23
src/App.tsx
|
@ -2,6 +2,9 @@ import { endOfMonth, format, startOfMonth } from "date-fns";
|
|||
import styles from "./App.module.scss";
|
||||
import Calendar from "./calendar/Calendar";
|
||||
import KeyboardShortcutWrapper from "./KeyboardShortcutWrapper";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export default function App() {
|
||||
const onDateClick = async (date: Date) => {
|
||||
|
@ -44,15 +47,17 @@ export default function App() {
|
|||
const exit = () => logseq.hideMainUI();
|
||||
|
||||
return (
|
||||
<KeyboardShortcutWrapper onExit={exit}>
|
||||
<main className={styles.app}>
|
||||
<div className="header">
|
||||
Header
|
||||
<button onClick={exit}>Close</button>
|
||||
</div>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<KeyboardShortcutWrapper onExit={exit}>
|
||||
<main className={styles.app}>
|
||||
<div className={styles.header}>
|
||||
Header
|
||||
<button onClick={exit}>Close</button>
|
||||
</div>
|
||||
|
||||
<Calendar onDateClick={onDateClick} />
|
||||
</main>
|
||||
</KeyboardShortcutWrapper>
|
||||
<Calendar onDateClick={onDateClick} />
|
||||
</main>
|
||||
</KeyboardShortcutWrapper>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
|
||||
.title {
|
||||
font-size: 22px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.controlButtons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import {
|
|||
} from "date-fns";
|
||||
import Month from "./Month";
|
||||
import { monthNameOf, weekBoundsOfMonth } from "lib/month";
|
||||
import { useJournals } from "lib/queries";
|
||||
import ToggleSwitch from "src/widgets/ToggleSwitch";
|
||||
|
||||
const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
const NUM_MONTHS_SHOWN = 5;
|
||||
|
@ -32,6 +34,9 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
range.map((x) => addMonths(centerMonth, x))
|
||||
);
|
||||
|
||||
const startDate = monthsShown[0];
|
||||
const endDate = monthsShown[NUM_MONTHS_SHOWN - 1];
|
||||
|
||||
const [firstLoad, setFirstLoad] = useState(true);
|
||||
useEffect(() => {
|
||||
if (firstLoad && scrollyEl && viewportHeight > 0) {
|
||||
|
@ -72,7 +77,7 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
useEffect(() => {
|
||||
if (!scrollyEl) return;
|
||||
|
||||
const children = [...scrollyEl.children];
|
||||
const children: HTMLElement[] = [...scrollyEl.children];
|
||||
if (children.length !== NUM_MONTHS_SHOWN) throw new Error("wtf");
|
||||
const firstChild = children[0];
|
||||
const lastChild = children[NUM_MONTHS_SHOWN - 1];
|
||||
|
@ -86,7 +91,7 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
|
||||
if (entry.target === firstChild) {
|
||||
console.log("intersected");
|
||||
const firstChildDate = new Date(firstChild.dataset.isodate);
|
||||
const firstChildDate = new Date(firstChild.dataset.isodate!);
|
||||
const prevMonth = subMonths(firstChildDate, 1);
|
||||
newMonthsShown = [prevMonth, ...monthsShown];
|
||||
newMonthsShown = newMonthsShown.slice(0, NUM_MONTHS_SHOWN);
|
||||
|
@ -96,7 +101,7 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
scrollyEl.scrollTop - firstChild.offsetTop,
|
||||
]);
|
||||
} else if (entry.target === lastChild) {
|
||||
const lastChildDate = new Date(lastChild.dataset.isodate);
|
||||
const lastChildDate = new Date(lastChild.dataset.isodate!);
|
||||
const nextMonth = addMonths(lastChildDate, 1);
|
||||
newMonthsShown = [...monthsShown, nextMonth];
|
||||
newMonthsShown = newMonthsShown.slice(-NUM_MONTHS_SHOWN);
|
||||
|
@ -139,19 +144,31 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
// middleMonthEl?.scrollIntoView();
|
||||
// }, [middleMonthRef]);
|
||||
|
||||
const [currentLayout, setCurrentLayout] = useState("Month");
|
||||
const [currentView, setCurrentView] = useState("Calendar");
|
||||
|
||||
return (
|
||||
<div className={styles.calendar}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
<b>{monthName}</b>
|
||||
{centerMonth.getFullYear()}
|
||||
(months shown:{" "}
|
||||
{JSON.stringify(
|
||||
monthsShown.map((x) =>
|
||||
x.toLocaleDateString("default", { month: "long" })
|
||||
)
|
||||
)}
|
||||
)
|
||||
<div>
|
||||
<b>{monthName}</b>
|
||||
{centerMonth.getFullYear()}
|
||||
</div>
|
||||
|
||||
<div className={styles.controlButtons}>
|
||||
<ToggleSwitch
|
||||
options={["Week", "Month", "Year"]}
|
||||
value={currentLayout}
|
||||
setValue={setCurrentLayout}
|
||||
/>
|
||||
|
||||
<ToggleSwitch
|
||||
options={["Calendar", "Graph"]}
|
||||
value={currentView}
|
||||
setValue={setCurrentView}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.daysOfWeek}>
|
||||
|
@ -173,6 +190,7 @@ export default function Calendar({ onDateClick }: CalendarProps) {
|
|||
const props = {
|
||||
month,
|
||||
dateGridHeight,
|
||||
dateCellHeight,
|
||||
};
|
||||
const ref = undefined;
|
||||
// (month === currentlyShownMonth && middleMonthRef) || undefined;
|
||||
|
|
|
@ -11,40 +11,26 @@ import {
|
|||
} from "date-fns";
|
||||
import classNames from "classnames";
|
||||
import { weekBoundsOfMonth } from "lib/month";
|
||||
import { journalFmt, useJournals } from "lib/queries";
|
||||
|
||||
interface MonthProps {
|
||||
month: Date;
|
||||
dateGridHeight: number;
|
||||
dateCellHeight: number;
|
||||
onDateClick?: (_: Date) => void;
|
||||
}
|
||||
|
||||
const monthColors = [
|
||||
"#AA3939",
|
||||
"#FFAAAA",
|
||||
"#D46A6A",
|
||||
"#801515",
|
||||
"#550000",
|
||||
"#AA6C39",
|
||||
"#FFD1AA",
|
||||
"#D49A6A",
|
||||
"#804515",
|
||||
"#552700",
|
||||
"#226666",
|
||||
"#669999",
|
||||
"#407F7F",
|
||||
"#0D4D4D",
|
||||
"#003333",
|
||||
"#2D882D",
|
||||
"#88CC88",
|
||||
"#55AA55",
|
||||
"#116611",
|
||||
"#004400",
|
||||
];
|
||||
|
||||
function Month({ month, dateGridHeight, onDateClick }: MonthProps, ref) {
|
||||
function Month(
|
||||
{ month, dateGridHeight, dateCellHeight, onDateClick }: MonthProps,
|
||||
ref
|
||||
) {
|
||||
const now = new Date();
|
||||
const monthName = month.toLocaleString("default", { month: "long" });
|
||||
|
||||
const firstDay = startOfMonth(month);
|
||||
const lastDay = endOfMonth(month);
|
||||
const { status, data: journals } = useJournals(firstDay, lastDay);
|
||||
|
||||
const [startWeek, endWeek] = weekBoundsOfMonth(month);
|
||||
const numWeeks = differenceInWeeks(endWeek, startWeek) + 1;
|
||||
const weeksArr = Array(numWeeks)
|
||||
|
@ -61,13 +47,18 @@ function Month({ month, dateGridHeight, onDateClick }: MonthProps, ref) {
|
|||
<>
|
||||
<div
|
||||
className={styles.dateGrid}
|
||||
style={{ height: `${dateGridHeight}px` }}
|
||||
// style={{ height: `${dateGridHeight}px` }}
|
||||
style={{ gridTemplateRows: `repeat(${numWeeks}, ${dateCellHeight}px)` }}
|
||||
ref={ref}
|
||||
data-isodate={month}
|
||||
>
|
||||
{datesArr.map((date) => {
|
||||
const isFirst = isSameDay(date, startOfMonth(date));
|
||||
const isToday = isSameDay(date, now);
|
||||
|
||||
const journalDate = journalFmt(date);
|
||||
const hasJournal = journals?.has(journalDate);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={date.toString()}
|
||||
|
@ -78,18 +69,15 @@ function Month({ month, dateGridHeight, onDateClick }: MonthProps, ref) {
|
|||
className={styles.dateNumber}
|
||||
onClick={() => onDateClick?.(date)}
|
||||
>
|
||||
<span
|
||||
className={classNames(isFirst && styles.today)}
|
||||
style={
|
||||
isFirst
|
||||
? { backgroundColor: monthColors[date.getMonth()] }
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<span className={classNames(isToday && styles.today)}>
|
||||
{isFirst && monthName}
|
||||
{date.getDate()}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className={styles.dateCellBody}>
|
||||
<p>j: {JSON.stringify(hasJournal)}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
:root {
|
||||
--text-color: black;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--text-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
|
@ -8,4 +16,5 @@ body,
|
|||
padding: 0;
|
||||
|
||||
font-family: sans-serif;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
|
19
src/widgets/ToggleSwitch.module.scss
Normal file
19
src/widgets/ToggleSwitch.module.scss
Normal file
|
@ -0,0 +1,19 @@
|
|||
.toggleSwitch {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
|
||||
border-radius: 9999px;
|
||||
background-color: lightgray;
|
||||
font-size: 14px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.option {
|
||||
border-radius: 9999px;
|
||||
padding: 4px 12px;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
background-color: gray;
|
||||
}
|
||||
}
|
33
src/widgets/ToggleSwitch.tsx
Normal file
33
src/widgets/ToggleSwitch.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import classNames from "classnames";
|
||||
import styles from "./ToggleSwitch.module.scss";
|
||||
|
||||
interface ToggleSwitchProps {
|
||||
options: string[];
|
||||
defaultOption?: string;
|
||||
value: string;
|
||||
setValue: (_: string) => any;
|
||||
}
|
||||
|
||||
export default function ToggleSwitch({
|
||||
options,
|
||||
defaultOption,
|
||||
value,
|
||||
setValue,
|
||||
}: ToggleSwitchProps) {
|
||||
return (
|
||||
<div className={styles.toggleSwitch}>
|
||||
{options.map((option) => {
|
||||
const isSelected = option === value;
|
||||
return (
|
||||
<div
|
||||
key={option}
|
||||
className={classNames(styles.option, isSelected && styles.selected)}
|
||||
onClick={() => setValue(option)}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue