Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
72dcb42147 | |||
64c80c11ba | |||
3e8fada7c7 | |||
45cc2e856c | |||
01c3912ba9 | |||
5ed921ec05 | |||
d1c7de593b | |||
4acf298044 | |||
a7ec7bf5eb | |||
78d996a989 | |||
f342b0fa25 | |||
8b57fd492d | |||
f8971e812e | |||
e420bb7ca2 | |||
41f688fd84 | |||
55aa6af239 | |||
922a8d24dd | |||
7192f527e9 | |||
4cf7878202 | |||
346df14a25 |
@ -15,17 +15,17 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Gitea Docker registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.grosinger.net
|
||||
username: tgrosinger
|
||||
password: ${{ secrets.CONTAINER_REGISTRY_ACCESS_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
@ -1,8 +1,8 @@
|
||||
FROM docker.io/library/node:18-alpine AS build-env
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV PORT 3000
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -17,4 +17,4 @@ RUN npm install
|
||||
COPY . .
|
||||
|
||||
# Run app command
|
||||
CMD ["/bin/ash", "/app/entrypoint.sh"]
|
||||
CMD ["/bin/ash", "/app/entrypoint.sh"]
|
||||
|
438
package-lock.json
generated
@ -8,16 +8,20 @@
|
||||
"name": "wscc-website",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "1.7.17",
|
||||
"@headlessui/react": "1.7.19",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@mapbox/rehype-prism": "^0.8.0",
|
||||
"@mdx-js/loader": "^2.3.0",
|
||||
"@mdx-js/react": "^2.3.0",
|
||||
"@next/mdx": "13.4.16",
|
||||
"@next/mdx": "14.2.2",
|
||||
"@stripe/react-stripe-js": "2.4.0",
|
||||
"@stripe/stripe-js": "2.2.1",
|
||||
"@tailwindcss/forms": "0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"@types/ical": "^0.8.3",
|
||||
"@types/react": "18.2.18",
|
||||
"@types/react-dom": "18.2.7",
|
||||
"@types/webpack-env": "^1.18.1",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"clsx": "^1.2.1",
|
||||
@ -25,23 +29,18 @@
|
||||
"fast-glob": "^3.2.11",
|
||||
"feed": "^4.2.2",
|
||||
"ical": "^0.8.0",
|
||||
"next": "13.4.16",
|
||||
"next-themes": "^0.2.1",
|
||||
"next": "14.2.2",
|
||||
"postmark": "4.0.2",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sharp": "0.32.6",
|
||||
"stripe": "14.9.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "5.1.6"
|
||||
"tailwindcss": "3.4.3",
|
||||
"typescript": "5.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ical": "^0.8.3",
|
||||
"@types/node": "20.4.7",
|
||||
"@types/react": "18.2.18",
|
||||
"@types/react-dom": "18.2.7",
|
||||
"@types/webpack-env": "^1.18.1",
|
||||
"eslint": "8.45.0",
|
||||
"eslint-config-next": "13.4.16",
|
||||
"prettier": "^3.0.1",
|
||||
@ -137,10 +136,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "1.7.17",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz",
|
||||
"integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==",
|
||||
"version": "1.7.19",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz",
|
||||
"integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==",
|
||||
"dependencies": {
|
||||
"@tanstack/react-virtual": "^3.0.0-beta.60",
|
||||
"client-only": "^0.0.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -339,9 +339,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.16.tgz",
|
||||
"integrity": "sha512-pCU0sJBqdfKP9mwDadxvZd+eLz3fZrTlmmDHY12Hdpl3DD0vy8ou5HWKVfG0zZS6tqhL4wnQqRbspdY5nqa7MA=="
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.2.tgz",
|
||||
"integrity": "sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw=="
|
||||
},
|
||||
"node_modules/@next/eslint-plugin-next": {
|
||||
"version": "13.4.16",
|
||||
@ -353,9 +353,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/mdx": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-13.4.16.tgz",
|
||||
"integrity": "sha512-4Yas2f0DFSi1BbtCAaMiv/EdGrBfflMEGBQf/QVAnVISihp/HwXiNhVN7wAt29vN9Mo/J4PtCKt8HQTYD7jbiA==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-14.2.2.tgz",
|
||||
"integrity": "sha512-Te60j1vMxbYWg2E1CiEuIjzWxjI8y6XKmLnhec0sYQupd7aTLm2bjFSLxei+kiQdWUYB87cmhazI9K2dbNB9wA==",
|
||||
"dependencies": {
|
||||
"source-map": "^0.7.0"
|
||||
},
|
||||
@ -373,9 +373,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.16.tgz",
|
||||
"integrity": "sha512-Rl6i1uUq0ciRa3VfEpw6GnWAJTSKo9oM2OrkGXPsm7rMxdd2FR5NkKc0C9xzFCI4+QtmBviWBdF2m3ur3Nqstw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.2.tgz",
|
||||
"integrity": "sha512-3iPgMhzbalizGwHNFUcGnDhFPSgVBHQ8aqSTAMxB5BvJG0oYrDf1WOJZlbXBgunOEj/8KMVbejEur/FpvFsgFQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -388,9 +388,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.16.tgz",
|
||||
"integrity": "sha512-o1vIKYbZORyDmTrPV1hApt9NLyWrS5vr2p5hhLGpOnkBY1cz6DAXjv8Lgan8t6X87+83F0EUDlu7klN8ieZ06A==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.2.tgz",
|
||||
"integrity": "sha512-x7Afi/jt0ZBRUZHTi49yyej4o8znfIMHO4RvThuoc0P+uli8Jd99y5GKjxoYunPKsXL09xBXEM1+OQy2xEL0Ag==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -403,9 +403,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.16.tgz",
|
||||
"integrity": "sha512-JRyAl8lCfyTng4zoOmE6hNI2f1MFUr7JyTYCHl1RxX42H4a5LMwJhDVQ7a9tmDZ/yj+0hpBn+Aan+d6lA3v0UQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.2.tgz",
|
||||
"integrity": "sha512-zbfPtkk7L41ODMJwSp5VbmPozPmMMQrzAc0HAUomVeVIIwlDGs/UCqLJvLNDt4jpWgc21SjjyIn762lNGrMaUA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -418,9 +418,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.16.tgz",
|
||||
"integrity": "sha512-9gqVqNzUMWbUDgDiND18xoUqhwSm2gmksqXgCU0qaOKt6oAjWz8cWYjgpPVD0WICKFylEY/gvPEP1fMZDVFZ/g==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.2.tgz",
|
||||
"integrity": "sha512-wPbS3pI/JU16rm3XdLvvTmlsmm1nd+sBa2ohXgBZcShX4TgOjD4R+RqHKlI1cjo/jDZKXt6OxmcU0Iys0OC/yg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -433,9 +433,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-gnu": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.16.tgz",
|
||||
"integrity": "sha512-KcQGwchAKmZVPa8i5PLTxvTs1/rcFnSltfpTm803Tr/BtBV3AxCkHLfhtoyVtVzx/kl/oue8oS+DSmbepQKwhw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.2.tgz",
|
||||
"integrity": "sha512-NqWOHqqq8iC9tuHvZxjQ2tX+jWy2X9y8NX2mcB4sj2bIccuCxbIZrU/ThFPZZPauygajZuVQ6zediejQHwZHwQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -448,9 +448,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-musl": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.16.tgz",
|
||||
"integrity": "sha512-2RbMZNxYnJmW8EPHVBsGZPq5zqWAyBOc/YFxq/jIQ/Yn3RMFZ1dZVCjtIcsiaKmgh7mjA/W0ApbumutHNxRqqQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.2.tgz",
|
||||
"integrity": "sha512-lGepHhwb9sGhCcU7999+iK1ZZT+6rrIoVg40MP7DZski9GIZP80wORSbt5kJzh9v2x2ev2lxC6VgwMQT0PcgTA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -463,9 +463,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-thDcGonELN7edUKzjzlHrdoKkm7y8IAdItQpRvvMxNUXa4d9r0ElofhTZj5emR7AiXft17hpen+QAkcWpqG7Jg==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-TZSh/48SfcLEQ4rD25VVn2kdIgUWmMflRX3OiyPwGNXn3NiyPqhqei/BaqCYXViIQ+6QsG9R0C8LftMqy8JPMA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -478,9 +478,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-f7SE1Mo4JAchUWl0LQsbtySR9xCa+x55C0taetjUApKtcLR3AgAjASrrP+oE1inmLmw573qRnE1eZN8YJfEBQw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-M0tBVNMEBJN2ZNQWlcekMn6pvLria7Sa2Fai5znm7CCJz4pP3lrvlSxhKdkCerk0D9E0bqx5yAo3o2Q7RrD4gA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -493,9 +493,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-WamDZm1M/OEM4QLce3lOmD1XdLEl37zYZwlmOLhmF7qYJ2G6oYm9+ejZVv+LakQIsIuXhSpVlOvrxIAHqwRkPQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-a/20E/wtTJZ3Ykv3f/8F0l7TtgQa2LWHU2oNB9bsu0VjqGuGGHmm/q6waoUNQYTVPYrrlxxaHjJcDV6aiSTt/w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -591,11 +591,17 @@
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.1.tgz",
|
||||
"integrity": "sha512-Wd81A0u8EwT3cf+Xv1mpMI18RbXVhgh19MtPcF9ojNTlG3kl36B1+XFe1KQfnJxD3WRnVfDuI0rNCK53mcGm6g=="
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
|
||||
},
|
||||
"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.5",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
|
||||
"integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
@ -647,6 +653,31 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-virtual": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.4.0.tgz",
|
||||
"integrity": "sha512-GZN4xn/Tg5w7gvYeVcMVCeL4pEyUhvg+Cp6KX2Z01C4FRNxIWMgIQ9ibgMarNQfo+gt0PVLcEER4A9sNv/jlow==",
|
||||
"dependencies": {
|
||||
"@tanstack/virtual-core": "3.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/virtual-core": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.4.0.tgz",
|
||||
"integrity": "sha512-75jXqXxqq5M5Veb9KP1STi8kA5u408uOOAefk2ftHDGCpUk3RP6zX++QqfbmHJTBiU72NQ+ghgCZVts/Wocz8Q==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/acorn": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
|
||||
@ -708,7 +739,6 @@
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ical/-/ical-0.8.3.tgz",
|
||||
"integrity": "sha512-qPejGORaXOstmqyKzp0Qw9nXDPiWiahiJJcx4zMB0zJVg0rLfJ6bDip/naqagEqYTjKl/LI91399hR8zFwRJ5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"rrule": "2.6.4"
|
||||
}
|
||||
@ -717,7 +747,6 @@
|
||||
"version": "2.6.4",
|
||||
"resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.4.tgz",
|
||||
"integrity": "sha512-sLdnh4lmjUqq8liFiOUXD5kWp/FcnbDLPwq5YAc/RrN6120XOPb86Ae5zxF7ttBVq8O3LxjjORMEit1baluahA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
@ -728,8 +757,7 @@
|
||||
"node_modules/@types/ical/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.12",
|
||||
@ -785,7 +813,6 @@
|
||||
"version": "18.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
||||
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@ -803,8 +830,7 @@
|
||||
"node_modules/@types/webpack-env": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.1.tgz",
|
||||
"integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==",
|
||||
"dev": true
|
||||
"integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.62.0",
|
||||
@ -1794,9 +1820,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001517",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
|
||||
"integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==",
|
||||
"version": "1.0.30001611",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001611.tgz",
|
||||
"integrity": "sha512-19NuN1/3PjA3QI8Eki55N8my4LzfkMCRLgCVfrl/slbSAchQfV0+GwjPrK3rq37As4UCLlM/DHajbKkAqbv92Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -3762,7 +3788,8 @@
|
||||
"node_modules/glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/global-dirs": {
|
||||
"version": "2.1.0",
|
||||
@ -4816,9 +4843,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
|
||||
"integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
|
||||
"integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
@ -7066,38 +7093,38 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-13.4.16.tgz",
|
||||
"integrity": "sha512-1xaA/5DrfpPu0eV31Iro7JfPeqO8uxQWb1zYNTe+KDKdzqkAGapLcDYHMLNKXKB7lHjZ7LfKUOf9dyuzcibrhA==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-14.2.2.tgz",
|
||||
"integrity": "sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg==",
|
||||
"dependencies": {
|
||||
"@next/env": "13.4.16",
|
||||
"@swc/helpers": "0.5.1",
|
||||
"@next/env": "14.2.2",
|
||||
"@swc/helpers": "0.5.5",
|
||||
"busboy": "1.6.0",
|
||||
"caniuse-lite": "^1.0.30001406",
|
||||
"postcss": "8.4.14",
|
||||
"styled-jsx": "5.1.1",
|
||||
"watchpack": "2.4.0",
|
||||
"zod": "3.21.4"
|
||||
"caniuse-lite": "^1.0.30001579",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"postcss": "8.4.31",
|
||||
"styled-jsx": "5.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"next": "dist/bin/next"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
"node": ">=18.17.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@next/swc-darwin-arm64": "13.4.16",
|
||||
"@next/swc-darwin-x64": "13.4.16",
|
||||
"@next/swc-linux-arm64-gnu": "13.4.16",
|
||||
"@next/swc-linux-arm64-musl": "13.4.16",
|
||||
"@next/swc-linux-x64-gnu": "13.4.16",
|
||||
"@next/swc-linux-x64-musl": "13.4.16",
|
||||
"@next/swc-win32-arm64-msvc": "13.4.16",
|
||||
"@next/swc-win32-ia32-msvc": "13.4.16",
|
||||
"@next/swc-win32-x64-msvc": "13.4.16"
|
||||
"@next/swc-darwin-arm64": "14.2.2",
|
||||
"@next/swc-darwin-x64": "14.2.2",
|
||||
"@next/swc-linux-arm64-gnu": "14.2.2",
|
||||
"@next/swc-linux-arm64-musl": "14.2.2",
|
||||
"@next/swc-linux-x64-gnu": "14.2.2",
|
||||
"@next/swc-linux-x64-musl": "14.2.2",
|
||||
"@next/swc-win32-arm64-msvc": "14.2.2",
|
||||
"@next/swc-win32-ia32-msvc": "14.2.2",
|
||||
"@next/swc-win32-x64-msvc": "14.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.1.0",
|
||||
"@playwright/test": "^1.41.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"sass": "^1.3.0"
|
||||
@ -7106,25 +7133,18 @@
|
||||
"@opentelemetry/api": {
|
||||
"optional": true
|
||||
},
|
||||
"@playwright/test": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-themes": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
|
||||
"integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==",
|
||||
"peerDependencies": {
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
@ -7133,10 +7153,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"
|
||||
},
|
||||
@ -9269,19 +9293,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
||||
"integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
|
||||
"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"arg": "^5.0.2",
|
||||
"chokidar": "^3.5.3",
|
||||
"didyoumean": "^1.2.2",
|
||||
"dlv": "^1.1.3",
|
||||
"fast-glob": "^3.2.12",
|
||||
"fast-glob": "^3.3.0",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"jiti": "^1.18.2",
|
||||
"jiti": "^1.21.0",
|
||||
"lilconfig": "^2.1.0",
|
||||
"micromatch": "^4.0.5",
|
||||
"normalize-path": "^3.0.0",
|
||||
@ -9651,9 +9675,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
|
||||
"integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@ -10061,6 +10085,7 @@
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
@ -10503,14 +10528,6 @@
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"node_modules/zwitch": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
||||
@ -10581,10 +10598,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@headlessui/react": {
|
||||
"version": "1.7.17",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz",
|
||||
"integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==",
|
||||
"version": "1.7.19",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz",
|
||||
"integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==",
|
||||
"requires": {
|
||||
"@tanstack/react-virtual": "^3.0.0-beta.60",
|
||||
"client-only": "^0.0.1"
|
||||
}
|
||||
},
|
||||
@ -10734,9 +10752,9 @@
|
||||
}
|
||||
},
|
||||
"@next/env": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.16.tgz",
|
||||
"integrity": "sha512-pCU0sJBqdfKP9mwDadxvZd+eLz3fZrTlmmDHY12Hdpl3DD0vy8ou5HWKVfG0zZS6tqhL4wnQqRbspdY5nqa7MA=="
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.2.tgz",
|
||||
"integrity": "sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw=="
|
||||
},
|
||||
"@next/eslint-plugin-next": {
|
||||
"version": "13.4.16",
|
||||
@ -10748,65 +10766,65 @@
|
||||
}
|
||||
},
|
||||
"@next/mdx": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-13.4.16.tgz",
|
||||
"integrity": "sha512-4Yas2f0DFSi1BbtCAaMiv/EdGrBfflMEGBQf/QVAnVISihp/HwXiNhVN7wAt29vN9Mo/J4PtCKt8HQTYD7jbiA==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-14.2.2.tgz",
|
||||
"integrity": "sha512-Te60j1vMxbYWg2E1CiEuIjzWxjI8y6XKmLnhec0sYQupd7aTLm2bjFSLxei+kiQdWUYB87cmhazI9K2dbNB9wA==",
|
||||
"requires": {
|
||||
"source-map": "^0.7.0"
|
||||
}
|
||||
},
|
||||
"@next/swc-darwin-arm64": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.16.tgz",
|
||||
"integrity": "sha512-Rl6i1uUq0ciRa3VfEpw6GnWAJTSKo9oM2OrkGXPsm7rMxdd2FR5NkKc0C9xzFCI4+QtmBviWBdF2m3ur3Nqstw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.2.tgz",
|
||||
"integrity": "sha512-3iPgMhzbalizGwHNFUcGnDhFPSgVBHQ8aqSTAMxB5BvJG0oYrDf1WOJZlbXBgunOEj/8KMVbejEur/FpvFsgFQ==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-darwin-x64": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.16.tgz",
|
||||
"integrity": "sha512-o1vIKYbZORyDmTrPV1hApt9NLyWrS5vr2p5hhLGpOnkBY1cz6DAXjv8Lgan8t6X87+83F0EUDlu7klN8ieZ06A==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.2.tgz",
|
||||
"integrity": "sha512-x7Afi/jt0ZBRUZHTi49yyej4o8znfIMHO4RvThuoc0P+uli8Jd99y5GKjxoYunPKsXL09xBXEM1+OQy2xEL0Ag==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-arm64-gnu": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.16.tgz",
|
||||
"integrity": "sha512-JRyAl8lCfyTng4zoOmE6hNI2f1MFUr7JyTYCHl1RxX42H4a5LMwJhDVQ7a9tmDZ/yj+0hpBn+Aan+d6lA3v0UQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.2.tgz",
|
||||
"integrity": "sha512-zbfPtkk7L41ODMJwSp5VbmPozPmMMQrzAc0HAUomVeVIIwlDGs/UCqLJvLNDt4jpWgc21SjjyIn762lNGrMaUA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-arm64-musl": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.16.tgz",
|
||||
"integrity": "sha512-9gqVqNzUMWbUDgDiND18xoUqhwSm2gmksqXgCU0qaOKt6oAjWz8cWYjgpPVD0WICKFylEY/gvPEP1fMZDVFZ/g==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.2.tgz",
|
||||
"integrity": "sha512-wPbS3pI/JU16rm3XdLvvTmlsmm1nd+sBa2ohXgBZcShX4TgOjD4R+RqHKlI1cjo/jDZKXt6OxmcU0Iys0OC/yg==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-x64-gnu": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.16.tgz",
|
||||
"integrity": "sha512-KcQGwchAKmZVPa8i5PLTxvTs1/rcFnSltfpTm803Tr/BtBV3AxCkHLfhtoyVtVzx/kl/oue8oS+DSmbepQKwhw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.2.tgz",
|
||||
"integrity": "sha512-NqWOHqqq8iC9tuHvZxjQ2tX+jWy2X9y8NX2mcB4sj2bIccuCxbIZrU/ThFPZZPauygajZuVQ6zediejQHwZHwQ==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-linux-x64-musl": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.16.tgz",
|
||||
"integrity": "sha512-2RbMZNxYnJmW8EPHVBsGZPq5zqWAyBOc/YFxq/jIQ/Yn3RMFZ1dZVCjtIcsiaKmgh7mjA/W0ApbumutHNxRqqQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.2.tgz",
|
||||
"integrity": "sha512-lGepHhwb9sGhCcU7999+iK1ZZT+6rrIoVg40MP7DZski9GIZP80wORSbt5kJzh9v2x2ev2lxC6VgwMQT0PcgTA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-arm64-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-thDcGonELN7edUKzjzlHrdoKkm7y8IAdItQpRvvMxNUXa4d9r0ElofhTZj5emR7AiXft17hpen+QAkcWpqG7Jg==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-TZSh/48SfcLEQ4rD25VVn2kdIgUWmMflRX3OiyPwGNXn3NiyPqhqei/BaqCYXViIQ+6QsG9R0C8LftMqy8JPMA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-ia32-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-f7SE1Mo4JAchUWl0LQsbtySR9xCa+x55C0taetjUApKtcLR3AgAjASrrP+oE1inmLmw573qRnE1eZN8YJfEBQw==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-M0tBVNMEBJN2ZNQWlcekMn6pvLria7Sa2Fai5znm7CCJz4pP3lrvlSxhKdkCerk0D9E0bqx5yAo3o2Q7RrD4gA==",
|
||||
"optional": true
|
||||
},
|
||||
"@next/swc-win32-x64-msvc": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.16.tgz",
|
||||
"integrity": "sha512-WamDZm1M/OEM4QLce3lOmD1XdLEl37zYZwlmOLhmF7qYJ2G6oYm9+ejZVv+LakQIsIuXhSpVlOvrxIAHqwRkPQ==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.2.tgz",
|
||||
"integrity": "sha512-a/20E/wtTJZ3Ykv3f/8F0l7TtgQa2LWHU2oNB9bsu0VjqGuGGHmm/q6waoUNQYTVPYrrlxxaHjJcDV6aiSTt/w==",
|
||||
"optional": true
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
@ -10870,11 +10888,17 @@
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.1.tgz",
|
||||
"integrity": "sha512-Wd81A0u8EwT3cf+Xv1mpMI18RbXVhgh19MtPcF9ojNTlG3kl36B1+XFe1KQfnJxD3WRnVfDuI0rNCK53mcGm6g=="
|
||||
},
|
||||
"@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
|
||||
},
|
||||
"@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.5",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
|
||||
"integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
|
||||
"requires": {
|
||||
"@swc/counter": "^0.1.3",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
@ -10916,6 +10940,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@tanstack/react-virtual": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.4.0.tgz",
|
||||
"integrity": "sha512-GZN4xn/Tg5w7gvYeVcMVCeL4pEyUhvg+Cp6KX2Z01C4FRNxIWMgIQ9ibgMarNQfo+gt0PVLcEER4A9sNv/jlow==",
|
||||
"requires": {
|
||||
"@tanstack/virtual-core": "3.4.0"
|
||||
}
|
||||
},
|
||||
"@tanstack/virtual-core": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.4.0.tgz",
|
||||
"integrity": "sha512-75jXqXxqq5M5Veb9KP1STi8kA5u408uOOAefk2ftHDGCpUk3RP6zX++QqfbmHJTBiU72NQ+ghgCZVts/Wocz8Q=="
|
||||
},
|
||||
"@types/acorn": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
|
||||
@ -10977,7 +11014,6 @@
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ical/-/ical-0.8.3.tgz",
|
||||
"integrity": "sha512-qPejGORaXOstmqyKzp0Qw9nXDPiWiahiJJcx4zMB0zJVg0rLfJ6bDip/naqagEqYTjKl/LI91399hR8zFwRJ5A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"rrule": "2.6.4"
|
||||
},
|
||||
@ -10986,7 +11022,6 @@
|
||||
"version": "2.6.4",
|
||||
"resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.4.tgz",
|
||||
"integrity": "sha512-sLdnh4lmjUqq8liFiOUXD5kWp/FcnbDLPwq5YAc/RrN6120XOPb86Ae5zxF7ttBVq8O3LxjjORMEit1baluahA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"luxon": "^1.21.3",
|
||||
"tslib": "^1.10.0"
|
||||
@ -10995,8 +11030,7 @@
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -11054,7 +11088,6 @@
|
||||
"version": "18.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
||||
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@ -11072,8 +11105,7 @@
|
||||
"@types/webpack-env": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.1.tgz",
|
||||
"integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==",
|
||||
"dev": true
|
||||
"integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww=="
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.62.0",
|
||||
@ -11795,9 +11827,9 @@
|
||||
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001517",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
|
||||
"integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA=="
|
||||
"version": "1.0.30001611",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001611.tgz",
|
||||
"integrity": "sha512-19NuN1/3PjA3QI8Eki55N8my4LzfkMCRLgCVfrl/slbSAchQfV0+GwjPrK3rq37As4UCLlM/DHajbKkAqbv92Q=="
|
||||
},
|
||||
"capture-stack-trace": {
|
||||
"version": "1.0.2",
|
||||
@ -13223,7 +13255,8 @@
|
||||
"glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"peer": true
|
||||
},
|
||||
"global-dirs": {
|
||||
"version": "2.1.0",
|
||||
@ -13933,9 +13966,9 @@
|
||||
}
|
||||
},
|
||||
"jiti": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
|
||||
"integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg=="
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
|
||||
"integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
@ -15514,47 +15547,40 @@
|
||||
"peer": true
|
||||
},
|
||||
"next": {
|
||||
"version": "13.4.16",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-13.4.16.tgz",
|
||||
"integrity": "sha512-1xaA/5DrfpPu0eV31Iro7JfPeqO8uxQWb1zYNTe+KDKdzqkAGapLcDYHMLNKXKB7lHjZ7LfKUOf9dyuzcibrhA==",
|
||||
"version": "14.2.2",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-14.2.2.tgz",
|
||||
"integrity": "sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg==",
|
||||
"requires": {
|
||||
"@next/env": "13.4.16",
|
||||
"@next/swc-darwin-arm64": "13.4.16",
|
||||
"@next/swc-darwin-x64": "13.4.16",
|
||||
"@next/swc-linux-arm64-gnu": "13.4.16",
|
||||
"@next/swc-linux-arm64-musl": "13.4.16",
|
||||
"@next/swc-linux-x64-gnu": "13.4.16",
|
||||
"@next/swc-linux-x64-musl": "13.4.16",
|
||||
"@next/swc-win32-arm64-msvc": "13.4.16",
|
||||
"@next/swc-win32-ia32-msvc": "13.4.16",
|
||||
"@next/swc-win32-x64-msvc": "13.4.16",
|
||||
"@swc/helpers": "0.5.1",
|
||||
"@next/env": "14.2.2",
|
||||
"@next/swc-darwin-arm64": "14.2.2",
|
||||
"@next/swc-darwin-x64": "14.2.2",
|
||||
"@next/swc-linux-arm64-gnu": "14.2.2",
|
||||
"@next/swc-linux-arm64-musl": "14.2.2",
|
||||
"@next/swc-linux-x64-gnu": "14.2.2",
|
||||
"@next/swc-linux-x64-musl": "14.2.2",
|
||||
"@next/swc-win32-arm64-msvc": "14.2.2",
|
||||
"@next/swc-win32-ia32-msvc": "14.2.2",
|
||||
"@next/swc-win32-x64-msvc": "14.2.2",
|
||||
"@swc/helpers": "0.5.5",
|
||||
"busboy": "1.6.0",
|
||||
"caniuse-lite": "^1.0.30001406",
|
||||
"postcss": "8.4.14",
|
||||
"styled-jsx": "5.1.1",
|
||||
"watchpack": "2.4.0",
|
||||
"zod": "3.21.4"
|
||||
"caniuse-lite": "^1.0.30001579",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"postcss": "8.4.31",
|
||||
"styled-jsx": "5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"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==",
|
||||
"requires": {
|
||||
"nanoid": "^3.3.4",
|
||||
"nanoid": "^3.3.6",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"next-themes": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
|
||||
"integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==",
|
||||
"requires": {}
|
||||
},
|
||||
"node-abi": {
|
||||
"version": "3.46.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.46.0.tgz",
|
||||
@ -16986,19 +17012,19 @@
|
||||
}
|
||||
},
|
||||
"tailwindcss": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
||||
"integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
|
||||
"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
|
||||
"requires": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"arg": "^5.0.2",
|
||||
"chokidar": "^3.5.3",
|
||||
"didyoumean": "^1.2.2",
|
||||
"dlv": "^1.1.3",
|
||||
"fast-glob": "^3.2.12",
|
||||
"fast-glob": "^3.3.0",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"jiti": "^1.18.2",
|
||||
"jiti": "^1.21.0",
|
||||
"lilconfig": "^2.1.0",
|
||||
"micromatch": "^4.0.5",
|
||||
"normalize-path": "^3.0.0",
|
||||
@ -17264,9 +17290,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
|
||||
"integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA=="
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="
|
||||
},
|
||||
"unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
@ -17551,6 +17577,7 @@
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
@ -17888,11 +17915,6 @@
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"zod": {
|
||||
"version": "3.21.4",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw=="
|
||||
},
|
||||
"zwitch": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
||||
|
13
package.json
@ -10,12 +10,12 @@
|
||||
},
|
||||
"browserslist": "defaults, not ie <= 11",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "1.7.17",
|
||||
"@headlessui/react": "1.7.19",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@mapbox/rehype-prism": "^0.8.0",
|
||||
"@mdx-js/loader": "^2.3.0",
|
||||
"@mdx-js/react": "^2.3.0",
|
||||
"@next/mdx": "13.4.16",
|
||||
"@next/mdx": "14.2.2",
|
||||
"@stripe/react-stripe-js": "2.4.0",
|
||||
"@stripe/stripe-js": "2.2.1",
|
||||
"@tailwindcss/forms": "0.5.7",
|
||||
@ -31,16 +31,15 @@
|
||||
"fast-glob": "^3.2.11",
|
||||
"feed": "^4.2.2",
|
||||
"ical": "^0.8.0",
|
||||
"next": "13.4.16",
|
||||
"next-themes": "^0.2.1",
|
||||
"next": "14.2.2",
|
||||
"postmark": "4.0.2",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sharp": "0.32.6",
|
||||
"stripe": "14.9.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "5.1.6"
|
||||
"tailwindcss": "3.4.3",
|
||||
"typescript": "5.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.4.7",
|
||||
@ -49,4 +48,4 @@
|
||||
"prettier": "^3.0.1",
|
||||
"prettier-plugin-tailwindcss": "^0.5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,10 @@ export async function POST(request: NextRequest): Promise<Response> {
|
||||
? `${billing.address.line1}\n${cityStateZip}`
|
||||
: `${billing.address.line1}\n${billing.address.line2}\n${cityStateZip}`;
|
||||
|
||||
const isDonation = data.metadata.type === 'donation';
|
||||
emailNotification({
|
||||
subject: isDonation ? 'New WSCC Donation' : 'New WSCC Membership',
|
||||
bodyPrefix: isDonation ? 'New donation:' : 'New WSCC member:',
|
||||
name: billing.name,
|
||||
type: data.metadata.type,
|
||||
amount: data.amount,
|
||||
|
@ -80,19 +80,19 @@ export default function Club() {
|
||||
<TableCell>Vice President</TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableLeftHeading>Tony Grosinger</TableLeftHeading>
|
||||
<TableLeftHeading>Beth Gasser</TableLeftHeading>
|
||||
<TableCell>Secretary</TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableLeftHeading>Temporarily performed by Secretary</TableLeftHeading>
|
||||
<TableLeftHeading>Tony Grosinger</TableLeftHeading>
|
||||
<TableCell>Treasurer</TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableLeftHeading>Mark Gasser</TableLeftHeading>
|
||||
<TableLeftHeading>Leslie Brown</TableLeftHeading>
|
||||
<TableCell>Director</TableCell>
|
||||
</tr>
|
||||
<tr>
|
||||
<TableLeftHeading>Leslie Brown</TableLeftHeading>
|
||||
<TableLeftHeading>Linn Hulley</TableLeftHeading>
|
||||
<TableCell>Director</TableCell>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -131,7 +131,7 @@ export const CalendarComponent: React.FC<{ calendar: Calendar }> = ({ calendar }
|
||||
</header>
|
||||
<div className="shadow ring-1 ring-black ring-opacity-5 lg:flex lg:flex-auto lg:flex-col">
|
||||
<div className="grid grid-cols-7 gap-px border-b border-zinc-100 bg-gray-200 text-center text-xs font-semibold leading-6 text-gray-700 lg:flex-none">
|
||||
{[['M', 'on'], ['T', 'ue'], ['W', 'ed'], ['T', 'hu'], ['F', 'ri'], ['S', 'at'], ['S', 'un']].map((d) => (
|
||||
{[['S', 'un'], ['M', 'on'], ['T', 'ue'], ['W', 'ed'], ['T', 'hu'], ['F', 'ri'], ['S', 'at']].map((d) => (
|
||||
<div key={d[0] + d[1]} className="bg-white py-2">
|
||||
{d[0]}<span className="sr-only sm:not-sr-only">{d[1]}</span>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@ import dayjs from "dayjs";
|
||||
import React from 'react';
|
||||
import { CalendarComponent } from "./calendar";
|
||||
import { Container } from "@/components/Container";
|
||||
import { Metadata } from "next";
|
||||
|
||||
const icalAddr = process.env.CALENDAR_ADDR || '';
|
||||
|
||||
@ -43,7 +44,13 @@ async function loadCalendar(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
const icalContents = await (await fetch(icalAddr)).text();
|
||||
console.log("Refreshing iCal from Google Calendar")
|
||||
|
||||
// For some reason Google Calendar is sending different content based on who is requesting it.
|
||||
const headers = new Headers();
|
||||
headers.set('User-Agent', 'curl/7.54.1');
|
||||
|
||||
const icalContents = await (await fetch(icalAddr, { headers })).text();
|
||||
const events = ical.parseICS(icalContents);
|
||||
const thisMonth = dayjs().startOf('month');
|
||||
const yesterday = dayjs().startOf('day').subtract(1, 'day');
|
||||
@ -103,6 +110,12 @@ async function loadCalendar(): Promise<void> {
|
||||
upcomingEvents = upcoming;
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Events Calendar',
|
||||
description:
|
||||
'Upcoming events and rentals ast the West Sound Hall.',
|
||||
}
|
||||
|
||||
export default async function Calendar() {
|
||||
const calendar = await getCalendar();
|
||||
|
||||
|
37
src/app/club/mailinglist.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
"use client"
|
||||
|
||||
export default function MailingListSignupForm(): React.JSX.Element {
|
||||
return (<form method="post" action="https://lists.orcas.community/subscription/form" className="listmonk-form">
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<h3 className="text-lg font-semibold text-gray-900">Join our mailing list</h3>
|
||||
<input type="hidden" name="nonce" />
|
||||
<div>
|
||||
<label htmlFor="email" className="sr-only">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
placeholder="you@example.com" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="name" className="sr-only">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
placeholder="Jane Doe" />
|
||||
</div>
|
||||
<input className="hidden" type="checkbox" name="l" checked value="ea5f1e67-2ff0-4762-8893-0645e93a8306" />
|
||||
<div className="h-captcha flex justify-center" data-sitekey="77aeddb4-cfda-4a3e-b262-0288a4e4664a"></div>
|
||||
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
|
||||
<input
|
||||
className="w-full rounded-md flex justify-center border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
id="submit"
|
||||
type="submit"
|
||||
value="Subscribe"
|
||||
/>
|
||||
</div>
|
||||
</form>);
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
import { type Metadata } from 'next';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import dynamic from 'next/dynamic';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { type Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import dynamic from "next/dynamic";
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import { UserPlusIcon, AtSymbolIcon, EnvelopeIcon, UserGroupIcon } from '@heroicons/react/24/solid'
|
||||
import interiorEmptyImage from '@/images/photos/interior-empty.jpg'
|
||||
import { Container } from '@/components/Container';
|
||||
import { EnvelopeIcon, UserGroupIcon } from '@heroicons/react/24/solid';
|
||||
import interiorEmptyImage from '@/images/photos/interior-empty.jpg';
|
||||
|
||||
function SocialLink({
|
||||
className,
|
||||
@ -15,10 +14,10 @@ function SocialLink({
|
||||
children,
|
||||
icon: Icon,
|
||||
}: {
|
||||
className?: string
|
||||
href: string
|
||||
icon: React.ComponentType<{ className?: string }>
|
||||
children: React.ReactNode
|
||||
className?: string;
|
||||
href: string;
|
||||
icon: React.ComponentType<{ className?: string }>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<li className={clsx(className, 'flex')}>
|
||||
@ -30,26 +29,30 @@ function SocialLink({
|
||||
<span className="ml-4">{children}</span>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'West Sound Community Club',
|
||||
description:
|
||||
'The West Sound Community Club on Orcas Island.',
|
||||
}
|
||||
|
||||
title: 'Community Club',
|
||||
description: 'The West Sound Community Club on Orcas Island.',
|
||||
};
|
||||
|
||||
// TODO: Replace interiorEmptyImage with a photo from a potluck
|
||||
|
||||
export default function Club() {
|
||||
|
||||
// Dynamic import since ClubPayment uses `document`
|
||||
const ClubPayment = dynamic(
|
||||
() => {
|
||||
return import("./payment");
|
||||
return import('./payment');
|
||||
},
|
||||
{ ssr: false }
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
const MailingListSignupForm = dynamic(
|
||||
() => {
|
||||
return import('./mailinglist');
|
||||
},
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
return (
|
||||
@ -71,38 +74,30 @@ export default function Club() {
|
||||
</h1>
|
||||
<div className="mt-6 space-y-7 text-base text-zinc-600">
|
||||
<p>
|
||||
The West Sound Community Club is a group of neighbors and friends
|
||||
living in the West Sound area. Together we steward the West Sound
|
||||
Hall, and gather monthly for potlucks and other community events.
|
||||
The West Sound Community Club is a group of neighbors and friends.
|
||||
Together we steward the West Sound Hall, and gather monthly for
|
||||
potlucks and other community events.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Members of the West Sound community, past and present, have
|
||||
invested time, money, and talent in creating a true old-fashioned
|
||||
community center. For over one hundred years, the hall has
|
||||
provided continuity for the residents and guests of the West Sound
|
||||
community. The current residents continue the commitment to
|
||||
maintain this unique gathering place out of care and respect for
|
||||
past and future generations.
|
||||
community center. For over 125, the hall has provided continuity
|
||||
for the residents and guests of the West Sound community. The
|
||||
current residents continue the commitment to maintain this unique
|
||||
gathering place out of care and respect for past and future
|
||||
generations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The West Sound Community Club is a nonprofit, tax-exempt corporation
|
||||
under Section 501(c)3 of the Internal Revenue Code.
|
||||
The West Sound Community Club is a nonprofit, tax-exempt
|
||||
corporation under Section 501(c)3 of the Internal Revenue Code.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:pl-20">
|
||||
<ul role="list">
|
||||
<SocialLink href="/WSCC-Membership-Form.pdf" icon={UserPlusIcon}>
|
||||
Membership Form
|
||||
</SocialLink>
|
||||
<SocialLink href="https://groups.orcashub.org/invites/YkP79vjDtz" icon={AtSymbolIcon} className="mt-4">
|
||||
Club Member Mailing List
|
||||
</SocialLink>
|
||||
<SocialLink href="https://groups.orcashub.org/invites/Lg87tP3G2V" icon={AtSymbolIcon} className="mt-4">
|
||||
West Sound Neighbor to Neighbor Mailing List
|
||||
</SocialLink>
|
||||
<MailingListSignupForm />
|
||||
<SocialLink
|
||||
href="mailto:contact@westsoundhall.org"
|
||||
icon={EnvelopeIcon}
|
||||
@ -110,18 +105,22 @@ export default function Club() {
|
||||
>
|
||||
contact@westsoundhall.org
|
||||
</SocialLink>
|
||||
<SocialLink href="/board-of-directors" icon={UserGroupIcon} className="mt-4">
|
||||
<SocialLink
|
||||
href="/board-of-directors"
|
||||
icon={UserGroupIcon}
|
||||
className="mt-4"
|
||||
>
|
||||
Board of Directors
|
||||
</SocialLink>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-2xl mb-4 font-semibold leading-6 text-gray-900">
|
||||
<h2 className="mb-4 text-2xl font-semibold leading-6 text-gray-900">
|
||||
Join or Renew your Membership
|
||||
</h2>
|
||||
<ClubPayment />
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState, FormEvent, useCallback } from 'react';
|
||||
import { AddressElement, Elements } from '@stripe/react-stripe-js';
|
||||
import { Appearance, StripeAddressElementOptions, StripeElementsOptions, loadStripe } from '@stripe/stripe-js';
|
||||
import {
|
||||
Appearance,
|
||||
StripeAddressElementOptions,
|
||||
StripeElementsOptions,
|
||||
loadStripe,
|
||||
} from '@stripe/stripe-js';
|
||||
import {
|
||||
PaymentElement,
|
||||
useStripe,
|
||||
useElements,
|
||||
} from '@stripe/react-stripe-js';
|
||||
import { RadioGroup } from '@headlessui/react'
|
||||
import { RadioGroup } from '@headlessui/react';
|
||||
|
||||
const stripe = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || '');
|
||||
|
||||
@ -20,15 +25,15 @@ const addressOptions: StripeAddressElementOptions = {
|
||||
},
|
||||
validation: {
|
||||
phone: {
|
||||
required: 'always'
|
||||
}
|
||||
required: 'always',
|
||||
},
|
||||
},
|
||||
defaultValues: {
|
||||
address: {
|
||||
state: 'WA',
|
||||
country: 'US',
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const membershipLevels = [
|
||||
@ -43,20 +48,40 @@ function classNames(...classes: string[]) {
|
||||
}
|
||||
|
||||
function Spinner(): React.JSX.Element {
|
||||
return (<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z">
|
||||
<animateTransform attributeName="transform" dur="1s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12" />
|
||||
</path>
|
||||
</svg>);
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"
|
||||
>
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
dur="1s"
|
||||
repeatCount="indefinite"
|
||||
type="rotate"
|
||||
values="0 12 12;360 12 12"
|
||||
/>
|
||||
</path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function CheckoutForm({
|
||||
paymentIntentID
|
||||
paymentIntentID,
|
||||
}: {
|
||||
paymentIntentID: string
|
||||
paymentIntentID: string;
|
||||
}): React.JSX.Element {
|
||||
const [selectedMembershipLevel, setSelectedMembershipLevel] = useState(membershipLevels[0]);
|
||||
const [selectedAdditionalDonation, setSelectedAdditionalDonation] = useState<number | null>(null);
|
||||
const [selectedMembershipLevel, setSelectedMembershipLevel] = useState(
|
||||
membershipLevels[0],
|
||||
);
|
||||
const [selectedAdditionalDonation, setSelectedAdditionalDonation] = useState<
|
||||
number | null
|
||||
>(null);
|
||||
const [customAmount, setCustomAmount] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [totalAmount, setTotalAmount] = useState(300);
|
||||
@ -72,7 +97,7 @@ function CheckoutForm({
|
||||
|
||||
//Grab the client secret from url params
|
||||
const clientSecret = new URLSearchParams(window.location.search).get(
|
||||
'payment_intent_client_secret'
|
||||
'payment_intent_client_secret',
|
||||
);
|
||||
|
||||
if (!clientSecret) {
|
||||
@ -98,19 +123,19 @@ function CheckoutForm({
|
||||
}, [stripe]);
|
||||
|
||||
useEffect(() => {
|
||||
let subtotal = selectedMembershipLevel.price
|
||||
let subtotal = selectedMembershipLevel.price;
|
||||
|
||||
if (selectedAdditionalDonation && selectedAdditionalDonation !== -1) {
|
||||
subtotal += selectedAdditionalDonation
|
||||
subtotal += selectedAdditionalDonation;
|
||||
} else if (customAmount !== '') {
|
||||
try {
|
||||
subtotal += parseFloat(customAmount)
|
||||
subtotal += parseFloat(customAmount);
|
||||
} catch {
|
||||
console.error('')
|
||||
console.error('');
|
||||
}
|
||||
}
|
||||
|
||||
subtotal = Math.ceil(subtotal * 1.03)
|
||||
subtotal = Math.ceil(subtotal * 1.03);
|
||||
|
||||
setTotalAmount(subtotal);
|
||||
|
||||
@ -121,11 +146,17 @@ function CheckoutForm({
|
||||
amount: subtotal * 100,
|
||||
payment_intent_id: paymentIntentID,
|
||||
metadata: {
|
||||
'type': selectedMembershipLevel.title,
|
||||
type: selectedMembershipLevel.title,
|
||||
},
|
||||
}),
|
||||
});
|
||||
}, [paymentIntentID, selectedMembershipLevel, selectedAdditionalDonation, customAmount, email])
|
||||
}, [
|
||||
paymentIntentID,
|
||||
selectedMembershipLevel,
|
||||
selectedAdditionalDonation,
|
||||
customAmount,
|
||||
email,
|
||||
]);
|
||||
|
||||
const handleSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
@ -162,10 +193,17 @@ function CheckoutForm({
|
||||
|
||||
return (
|
||||
<>
|
||||
<form id="payment-form" onSubmit={handleSubmit} className="m-auto space-y-4">
|
||||
|
||||
<form
|
||||
id="payment-form"
|
||||
onSubmit={handleSubmit}
|
||||
className="m-auto space-y-4"
|
||||
>
|
||||
{/* Membership Type */}
|
||||
<RadioGroup value={selectedMembershipLevel} onChange={setSelectedMembershipLevel} className="space-y-3">
|
||||
<RadioGroup
|
||||
value={selectedMembershipLevel}
|
||||
onChange={setSelectedMembershipLevel}
|
||||
className="space-y-3"
|
||||
>
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900">
|
||||
Select a membership type
|
||||
</RadioGroup.Label>
|
||||
@ -177,8 +215,10 @@ function CheckoutForm({
|
||||
value={membership}
|
||||
className={({ active }) =>
|
||||
classNames(
|
||||
active ? 'border-indigo-600 ring-2 ring-indigo-600' : 'border-gray-200',
|
||||
'relative flex cursor-pointer rounded-lg border bg-white hover:bg-gray-50 p-4 shadow-sm focus:outline-none'
|
||||
active
|
||||
? 'border-indigo-600 ring-2 ring-indigo-600'
|
||||
: 'border-gray-200',
|
||||
'relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm hover:bg-gray-50 focus:outline-none',
|
||||
)
|
||||
}
|
||||
>
|
||||
@ -186,15 +226,26 @@ function CheckoutForm({
|
||||
<>
|
||||
<span className="flex flex-1 items-center justify-between ">
|
||||
<span className="flex flex-col">
|
||||
<RadioGroup.Label as="span" className="block text-sm font-medium text-gray-900">
|
||||
<RadioGroup.Label
|
||||
as="span"
|
||||
className="block text-sm font-medium text-gray-900"
|
||||
>
|
||||
{membership.title}
|
||||
</RadioGroup.Label>
|
||||
<RadioGroup.Description as="span" className="mt-1 flex items-center text-sm text-gray-500">
|
||||
<RadioGroup.Description
|
||||
as="span"
|
||||
className="mt-1 flex items-center text-sm text-gray-500"
|
||||
>
|
||||
{membership.description}
|
||||
</RadioGroup.Description>
|
||||
</span>
|
||||
<RadioGroup.Description as="span" className="ml-8 text-sm font-medium">
|
||||
<span className="text-gray-900">${membership.price}</span>
|
||||
<RadioGroup.Description
|
||||
as="span"
|
||||
className="ml-8 text-sm font-medium"
|
||||
>
|
||||
<span className="text-gray-900">
|
||||
${membership.price}
|
||||
</span>
|
||||
<span className="text-gray-500">/yr</span>
|
||||
</RadioGroup.Description>
|
||||
</span>
|
||||
@ -202,7 +253,7 @@ function CheckoutForm({
|
||||
className={classNames(
|
||||
active ? 'border' : 'border-2',
|
||||
checked ? 'border-indigo-600' : 'border-transparent',
|
||||
'pointer-events-none absolute -inset-px rounded-lg'
|
||||
'pointer-events-none absolute -inset-px rounded-lg',
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
@ -214,7 +265,11 @@ function CheckoutForm({
|
||||
</RadioGroup>
|
||||
|
||||
{/* Additional donation */}
|
||||
<RadioGroup value={selectedAdditionalDonation} onChange={setSelectedAdditionalDonation} className="space-y-3">
|
||||
<RadioGroup
|
||||
value={selectedAdditionalDonation}
|
||||
onChange={setSelectedAdditionalDonation}
|
||||
className="space-y-3"
|
||||
>
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900">
|
||||
Additional donation
|
||||
</RadioGroup.Label>
|
||||
@ -229,45 +284,48 @@ function CheckoutForm({
|
||||
option === -1 ? 'col-span-2' : '',
|
||||
checked
|
||||
? 'ring-2 ring-indigo-600'
|
||||
: 'ring-1 ring-inset ring-gray-200 text-gray-900 hover:bg-gray-50',
|
||||
'flex items-center justify-center rounded-md py-3 px-3 text-sm font-semibold sm:flex-1 bg-white'
|
||||
: 'text-gray-900 ring-1 ring-inset ring-gray-200 hover:bg-gray-50',
|
||||
'flex items-center justify-center rounded-md bg-white px-3 py-3 text-sm font-semibold sm:flex-1',
|
||||
)
|
||||
}
|
||||
>
|
||||
|
||||
{option === -1
|
||||
? (
|
||||
<RadioGroup.Label as="span" className="flex flex-col items-center">
|
||||
<div className="relative rounded-md shadow-sm">
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<span className="text-gray-500 sm:text-sm">$</span>
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
name="custom-amount"
|
||||
id="custom-amount"
|
||||
value={customAmount}
|
||||
min="0"
|
||||
step="1"
|
||||
onChange={(e) => setCustomAmount(e.target.value)}
|
||||
className="block w-full rounded-md border-0 py-1.5 pl-7 pr-12 text-gray-900 ring-1 ring-inset ring-gray-200 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-gray-500 sm:text-sm sm:leading-6"
|
||||
placeholder="Custom"
|
||||
aria-describedby="price-currency"
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
|
||||
<span className="text-gray-500 sm:text-sm" id="price-currency">
|
||||
/yr
|
||||
</span>
|
||||
</div>
|
||||
{option === -1 ? (
|
||||
<RadioGroup.Label
|
||||
as="span"
|
||||
className="flex flex-col items-center"
|
||||
>
|
||||
<div className="relative rounded-md shadow-sm">
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<span className="text-gray-500 sm:text-sm">$</span>
|
||||
</div>
|
||||
</RadioGroup.Label>
|
||||
)
|
||||
: (
|
||||
<RadioGroup.Label as="span">
|
||||
<span>${option}</span>
|
||||
<span className="text-gray-500">/yr</span>
|
||||
</RadioGroup.Label>
|
||||
)}
|
||||
<input
|
||||
type="number"
|
||||
name="custom-amount"
|
||||
id="custom-amount"
|
||||
value={customAmount}
|
||||
min="0"
|
||||
step="1"
|
||||
onChange={(e) => setCustomAmount(e.target.value)}
|
||||
className="block w-full rounded-md border-0 py-1.5 pl-7 pr-12 text-gray-900 ring-1 ring-inset ring-gray-200 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-gray-500 sm:text-sm sm:leading-6"
|
||||
placeholder="Custom"
|
||||
aria-describedby="price-currency"
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
|
||||
<span
|
||||
className="text-gray-500 sm:text-sm"
|
||||
id="price-currency"
|
||||
>
|
||||
/yr
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</RadioGroup.Label>
|
||||
) : (
|
||||
<RadioGroup.Label as="span">
|
||||
<span>${option}</span>
|
||||
<span className="text-gray-500">/yr</span>
|
||||
</RadioGroup.Label>
|
||||
)}
|
||||
</RadioGroup.Option>
|
||||
))}
|
||||
</div>
|
||||
@ -278,8 +336,11 @@ function CheckoutForm({
|
||||
About you
|
||||
</h2>
|
||||
|
||||
<div className="rounded-md mb-3 px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-200 focus-within:ring-2 focus-within:ring-indigo-600">
|
||||
<label htmlFor="name" className="block text-xs font-medium text-gray-900">
|
||||
<div className="mb-3 rounded-md px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-200 focus-within:ring-2 focus-within:ring-indigo-600">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-xs font-medium text-gray-900"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
@ -301,9 +362,15 @@ function CheckoutForm({
|
||||
</h2>
|
||||
<div className="mt-1 text-sm text-gray-500">
|
||||
Credit card fees included. If you would like to avoid these fees or
|
||||
to pay by cash or check, please instead <a className="underline
|
||||
mx-1" href="/WSCC-Membership-Form.pdf">fill out a paper form</a> and
|
||||
mail to the address on the form.
|
||||
to pay by cash or check, please instead{' '}
|
||||
<a
|
||||
className="mx-1
|
||||
underline"
|
||||
href="/WSCC-Membership-Form.pdf"
|
||||
>
|
||||
fill out a paper form
|
||||
</a>{' '}
|
||||
and mail to the address on the form.
|
||||
</div>
|
||||
<PaymentElement id="payment-element" />
|
||||
</div>
|
||||
@ -311,19 +378,19 @@ function CheckoutForm({
|
||||
{/* TODO: Automatically renew toggle? */}
|
||||
|
||||
<button
|
||||
className="mt-6 w-full rounded-md flex justify-center border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
className="mt-6 flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
disabled={isLoading || !stripe || !elements}
|
||||
id="submit"
|
||||
>
|
||||
{isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
'Pay $' + totalAmount
|
||||
)}
|
||||
{isLoading ? <Spinner /> : 'Pay $' + totalAmount}
|
||||
</button>
|
||||
|
||||
{/* Show any error or success messages */}
|
||||
{message && <div className="text-red-500" id="payment-message">{message}</div>}
|
||||
{message && (
|
||||
<div className="text-red-500" id="payment-message">
|
||||
{message}
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
@ -333,26 +400,6 @@ const DEFAULT_OPTIONS = {
|
||||
config: { attributes: true, childList: true, subtree: true },
|
||||
};
|
||||
|
||||
function useMutationObservable(targetEl: Node, cb: MutationCallback, options = DEFAULT_OPTIONS) {
|
||||
const [observer, setObserver] = useState<MutationObserver | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const obs = new MutationObserver(cb);
|
||||
setObserver(obs);
|
||||
}, [cb, options, setObserver]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!observer) return;
|
||||
const { config } = options;
|
||||
observer.observe(targetEl, config);
|
||||
return () => {
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
}
|
||||
};
|
||||
}, [observer, targetEl, options]);
|
||||
}
|
||||
|
||||
export default function ClubPayment() {
|
||||
const [clientSecret, setClientSecret] = useState('');
|
||||
const [paymentIntent, setPaymentIntent] = useState('');
|
||||
@ -390,16 +437,15 @@ export default function ClubPayment() {
|
||||
const options: StripeElementsOptions = {
|
||||
clientSecret,
|
||||
appearance,
|
||||
}
|
||||
};
|
||||
|
||||
return <>
|
||||
{clientSecret && (
|
||||
<Elements options={options}
|
||||
stripe={stripe}>
|
||||
<CheckoutForm paymentIntentID={paymentIntent} />
|
||||
</Elements>
|
||||
)}
|
||||
</>
|
||||
return (
|
||||
<>
|
||||
{clientSecret && (
|
||||
<Elements options={options} stripe={stripe}>
|
||||
<CheckoutForm paymentIntentID={paymentIntent} />
|
||||
</Elements>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
46
src/app/donate/page.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { type Metadata } from 'next';
|
||||
import Image from 'next/image';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
import { Container } from '@/components/Container';
|
||||
import logoImage from '@/images/logo.png';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Donate',
|
||||
description: 'Donate to the West Sound Community Club.',
|
||||
};
|
||||
|
||||
export default function Donate() {
|
||||
// Dynamic import since DontationPayment uses `document`
|
||||
const DontationPayment = dynamic(
|
||||
() => {
|
||||
return import('./payment');
|
||||
},
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
return (
|
||||
<Container className="mx-auto mt-16 max-w-3xl sm:mt-32">
|
||||
<div className="px-2.5">
|
||||
<Image
|
||||
src={logoImage}
|
||||
alt=""
|
||||
sizes="(min-width: 1024px) 32rem, 20rem"
|
||||
/>
|
||||
</div>
|
||||
<div className="my-6 space-y-7 text-base text-zinc-600">
|
||||
<p>
|
||||
Your donation to the West Sound Community Club helps keep the hall
|
||||
alive for the next generation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The West Sound Community Club is a nonprofit, tax-exempt corporation
|
||||
under Section 501(c)3 of the Internal Revenue Code. Your donations are
|
||||
tax-deductible.
|
||||
</p>
|
||||
</div>
|
||||
<DontationPayment />
|
||||
</Container>
|
||||
);
|
||||
}
|
341
src/app/donate/payment.tsx
Normal file
@ -0,0 +1,341 @@
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState, FormEvent } from 'react';
|
||||
import { AddressElement, Elements } from '@stripe/react-stripe-js';
|
||||
import {
|
||||
Appearance,
|
||||
StripeAddressElementOptions,
|
||||
StripeElementsOptions,
|
||||
loadStripe,
|
||||
} from '@stripe/stripe-js';
|
||||
import {
|
||||
PaymentElement,
|
||||
useStripe,
|
||||
useElements,
|
||||
} from '@stripe/react-stripe-js';
|
||||
import { RadioGroup } from '@headlessui/react';
|
||||
|
||||
const stripe = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || '');
|
||||
|
||||
const addressOptions: StripeAddressElementOptions = {
|
||||
mode: 'billing',
|
||||
allowedCountries: ['US'],
|
||||
fields: {
|
||||
phone: 'always',
|
||||
},
|
||||
validation: {
|
||||
phone: {
|
||||
required: 'always',
|
||||
},
|
||||
},
|
||||
defaultValues: {
|
||||
address: {
|
||||
state: 'WA',
|
||||
country: 'US',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const donationLevels = [10, 50, 100, -1];
|
||||
|
||||
function classNames(...classes: string[]) {
|
||||
return classes.filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
function Spinner(): React.JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"
|
||||
>
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
dur="1s"
|
||||
repeatCount="indefinite"
|
||||
type="rotate"
|
||||
values="0 12 12;360 12 12"
|
||||
/>
|
||||
</path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function CheckoutForm({
|
||||
paymentIntentID,
|
||||
}: {
|
||||
paymentIntentID: string;
|
||||
}): React.JSX.Element {
|
||||
const [selectedDonation, setSelectedDonation] = useState<number>(10);
|
||||
const [customAmount, setCustomAmount] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [totalAmount, setTotalAmount] = useState(300);
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const stripe = useStripe();
|
||||
const elements = useElements();
|
||||
|
||||
useEffect(() => {
|
||||
if (!stripe) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Grab the client secret from url params
|
||||
const clientSecret = new URLSearchParams(window.location.search).get(
|
||||
'payment_intent_client_secret',
|
||||
);
|
||||
|
||||
if (!clientSecret) {
|
||||
return;
|
||||
}
|
||||
|
||||
stripe.retrievePaymentIntent(clientSecret).then(({ paymentIntent }) => {
|
||||
switch (paymentIntent?.status) {
|
||||
case 'succeeded':
|
||||
setMessage('Payment succeeded!');
|
||||
break;
|
||||
case 'processing':
|
||||
setMessage('Your payment is processing.');
|
||||
break;
|
||||
case 'requires_payment_method':
|
||||
setMessage('Your payment was not successful, please try again.');
|
||||
break;
|
||||
default:
|
||||
setMessage('Something went wrong.');
|
||||
break;
|
||||
}
|
||||
});
|
||||
}, [stripe]);
|
||||
|
||||
useEffect(() => {
|
||||
let subtotal = 0;
|
||||
|
||||
if (selectedDonation && selectedDonation !== -1) {
|
||||
subtotal += selectedDonation;
|
||||
} else if (customAmount !== '') {
|
||||
try {
|
||||
subtotal += parseFloat(customAmount);
|
||||
} catch {
|
||||
console.error('');
|
||||
}
|
||||
}
|
||||
|
||||
setTotalAmount(subtotal);
|
||||
|
||||
fetch('api/stripe_intent', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
amount: subtotal * 100,
|
||||
payment_intent_id: paymentIntentID,
|
||||
}),
|
||||
});
|
||||
}, [paymentIntentID, selectedDonation, customAmount, email]);
|
||||
|
||||
const handleSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!stripe || !elements) {
|
||||
// Stripe.js has not yet loaded.
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const { error } = await stripe.confirmPayment({
|
||||
elements,
|
||||
confirmParams: {
|
||||
return_url: window.location.origin + '/donate/thank-you',
|
||||
receipt_email: email,
|
||||
payment_method_data: {
|
||||
billing_details: {
|
||||
// Other details are filled automatically by address form.
|
||||
email,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (error.type === 'card_error' || error.type === 'validation_error') {
|
||||
setMessage(error.message || '');
|
||||
} else {
|
||||
setMessage('An unexpected error occured.');
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<form
|
||||
id="payment-form"
|
||||
onSubmit={handleSubmit}
|
||||
className="m-auto space-y-4"
|
||||
>
|
||||
{/* Amount */}
|
||||
<RadioGroup
|
||||
value={selectedDonation}
|
||||
onChange={setSelectedDonation}
|
||||
className="space-y-3"
|
||||
>
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900">
|
||||
Donation amount
|
||||
</RadioGroup.Label>
|
||||
<div className="grid grid-cols-3 gap-3 sm:grid-cols-5">
|
||||
{donationLevels.map((option) => (
|
||||
<RadioGroup.Option
|
||||
key={option}
|
||||
value={option}
|
||||
className={({ active, checked }) =>
|
||||
classNames(
|
||||
'cursor-pointer focus:outline-none',
|
||||
option === -1 ? 'col-span-2' : '',
|
||||
checked
|
||||
? 'ring-2 ring-indigo-600'
|
||||
: 'text-gray-900 ring-1 ring-inset ring-gray-200 hover:bg-gray-50',
|
||||
'flex items-center justify-center rounded-md bg-white px-3 py-3 text-sm font-semibold sm:flex-1',
|
||||
)
|
||||
}
|
||||
>
|
||||
{option === -1 ? (
|
||||
<RadioGroup.Label
|
||||
as="span"
|
||||
className="flex flex-col items-center"
|
||||
>
|
||||
<div className="relative rounded-md shadow-sm">
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<span className="text-gray-500 sm:text-sm">$</span>
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
name="custom-amount"
|
||||
id="custom-amount"
|
||||
value={customAmount}
|
||||
min="0"
|
||||
step="1"
|
||||
onChange={(e) => setCustomAmount(e.target.value)}
|
||||
className="block w-full rounded-md border-0 py-1.5 pl-7 pr-2 text-gray-900 ring-1 ring-inset ring-gray-200 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-gray-500 sm:text-sm sm:leading-6"
|
||||
placeholder="Custom"
|
||||
aria-describedby="price-currency"
|
||||
/>
|
||||
</div>
|
||||
</RadioGroup.Label>
|
||||
) : (
|
||||
<RadioGroup.Label as="span">
|
||||
<span>${option}</span>
|
||||
</RadioGroup.Label>
|
||||
)}
|
||||
</RadioGroup.Option>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
|
||||
<div className="space-y-3">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900">
|
||||
About you
|
||||
</h2>
|
||||
|
||||
<div className="mb-3 rounded-md px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-200 focus-within:ring-2 focus-within:ring-indigo-600">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-xs font-medium text-gray-900"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
</div>
|
||||
<AddressElement options={addressOptions} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900">
|
||||
Payment
|
||||
</h2>
|
||||
<PaymentElement id="payment-element" />
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="mt-6 flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
disabled={isLoading || !stripe || !elements}
|
||||
id="submit"
|
||||
>
|
||||
{isLoading ? <Spinner /> : 'Pay $' + totalAmount}
|
||||
</button>
|
||||
|
||||
{/* Show any error or success messages */}
|
||||
{message && (
|
||||
<div className="text-red-500" id="payment-message">
|
||||
{message}
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
config: { attributes: true, childList: true, subtree: true },
|
||||
};
|
||||
|
||||
export default function DontationPayment() {
|
||||
const [clientSecret, setClientSecret] = useState('');
|
||||
const [paymentIntent, setPaymentIntent] = useState('');
|
||||
|
||||
const htmlEl = document.getElementsByTagName('html')[0];
|
||||
|
||||
useEffect(() => {
|
||||
// Create PaymentIntent as soon as the page loads using our local API
|
||||
fetch('api/stripe_intent', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
amount: 2000,
|
||||
payment_intent_id: '',
|
||||
}),
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setClientSecret(data.client_secret);
|
||||
setPaymentIntent(data.id);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const styles = getComputedStyle(htmlEl);
|
||||
|
||||
const appearance: Appearance = {
|
||||
theme: 'stripe',
|
||||
variables: {
|
||||
colorBackground: styles.getPropertyValue('--stripe-background'),
|
||||
colorText: styles.getPropertyValue('--stripe-foreground'),
|
||||
},
|
||||
labels: 'floating',
|
||||
};
|
||||
|
||||
const options: StripeElementsOptions = {
|
||||
clientSecret,
|
||||
appearance,
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{clientSecret && (
|
||||
<Elements options={options} stripe={stripe}>
|
||||
<CheckoutForm paymentIntentID={paymentIntent} />
|
||||
</Elements>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
31
src/app/donate/thank-you/page.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { type Metadata } from 'next';
|
||||
|
||||
import { SimpleLayout } from '@/components/SimpleLayout';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Thank You',
|
||||
description: 'Thanks for donating.',
|
||||
};
|
||||
|
||||
export default async function ThankYou({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: { [key: string]: string | string[] | undefined };
|
||||
}) {
|
||||
const { redirect_status } = searchParams;
|
||||
if (redirect_status !== 'succeeded') {
|
||||
// TODO: Display error
|
||||
}
|
||||
|
||||
return (
|
||||
<SimpleLayout
|
||||
title="Thanks for donating."
|
||||
intro="Thank you for donating to the West Sound Community Club."
|
||||
>
|
||||
<p className="text-base text-zinc-600">
|
||||
Your financial support helps us perserve this historic building and to
|
||||
host events for the community.
|
||||
</p>
|
||||
</SimpleLayout>
|
||||
);
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import { type Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
import { Card } from '@/components/Card'
|
||||
import { type Metadata } from 'next';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import clsx from 'clsx';
|
||||
import { Card } from '@/components/Card';
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import originalDeedImage from '@/images/original-deed.png'
|
||||
import { EnvelopeIcon } from '@heroicons/react/24/solid'
|
||||
import { Container } from '@/components/Container';
|
||||
import originalDeedImage from '@/images/original-deed.png';
|
||||
import { EnvelopeIcon } from '@heroicons/react/24/solid';
|
||||
|
||||
function SocialLink({
|
||||
className,
|
||||
@ -14,10 +14,10 @@ function SocialLink({
|
||||
children,
|
||||
icon: Icon,
|
||||
}: {
|
||||
className?: string
|
||||
href: string
|
||||
icon: React.ComponentType<{ className?: string }>
|
||||
children: React.ReactNode
|
||||
className?: string;
|
||||
href: string;
|
||||
icon: React.ComponentType<{ className?: string }>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<li className={clsx(className, 'flex')}>
|
||||
@ -29,7 +29,7 @@ function SocialLink({
|
||||
<span className="ml-4">{children}</span>
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function TimelineEntry({
|
||||
@ -38,51 +38,41 @@ function TimelineEntry({
|
||||
event,
|
||||
cta,
|
||||
href,
|
||||
children
|
||||
children,
|
||||
}: {
|
||||
title: string
|
||||
description: string
|
||||
event?: string
|
||||
cta?: string
|
||||
href?: string
|
||||
children?: React.ReactNode
|
||||
title: string;
|
||||
description: string;
|
||||
event?: string;
|
||||
cta?: string;
|
||||
href?: string;
|
||||
children?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<Card as="article">
|
||||
<Card.Title as="h3" href={href}>
|
||||
{title}
|
||||
</Card.Title>
|
||||
{event
|
||||
? <Card.Eyebrow decorate>{event}</Card.Eyebrow>
|
||||
: null}
|
||||
{event ? <Card.Eyebrow decorate>{event}</Card.Eyebrow> : null}
|
||||
<Card.Description>{description}</Card.Description>
|
||||
{cta
|
||||
? <Card.Cta>{cta}</Card.Cta>
|
||||
: null}
|
||||
{cta ? <Card.Cta>{cta}</Card.Cta> : null}
|
||||
{children}
|
||||
</Card>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function DateListItem({
|
||||
year, value
|
||||
}: {
|
||||
year?: string
|
||||
value: string
|
||||
}) {
|
||||
function DateListItem({ year, value }: { year?: string; value: string }) {
|
||||
return (
|
||||
<div className='flex space-x-4'>
|
||||
<div className='w-10'>{year}</div>
|
||||
<div className="flex space-x-4">
|
||||
<div className="w-10">{year}</div>
|
||||
<div>{value}</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'West Sound Hall History',
|
||||
description:
|
||||
'The history of the West Sound Community Hall on Orcas Island.',
|
||||
}
|
||||
title: 'Hall History',
|
||||
description: 'The history of the West Sound Community Hall on Orcas Island.',
|
||||
};
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
@ -108,15 +98,15 @@ export default function About() {
|
||||
<div className="mt-6 space-y-7 text-base text-zinc-600">
|
||||
<p>
|
||||
The West Sound Community Hall represents the history and character
|
||||
of Orcas Island. Members of the nonprofit West Sound Community Club,
|
||||
as stewards of the Hall, strive to maintain the integrity of the
|
||||
Hall as a unique gathering place for future generations.
|
||||
of Orcas Island. Members of the nonprofit West Sound Community
|
||||
Club, as stewards of the Hall, strive to maintain the integrity of
|
||||
the Hall as a unique gathering place for future generations.
|
||||
</p>
|
||||
<p>
|
||||
In 1902 volunteers began building the Hall with materials supplied by George
|
||||
Adkins. The building site was donated two years earlier by Alexander Chalmers.
|
||||
The Hall was erected to serve as a central meeting place for residents of the
|
||||
West Sound area.
|
||||
In 1902 volunteers began building the Hall with materials supplied
|
||||
by George Adkins. The building site was donated two years earlier
|
||||
by Alexander Chalmers. The Hall was erected to serve as a central
|
||||
meeting place for residents of the West Sound area.
|
||||
</p>
|
||||
<p>
|
||||
Over the years the original one-room schoolhouse design has
|
||||
@ -143,120 +133,105 @@ export default function About() {
|
||||
description='Alexander Chalmers donated "property to be used for a site for a public hall" to the West Sound Hall Company. The donated land was originally part of a large parcel homesteaded by Peter LaPlante in 1884.'
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1902 - 1903'
|
||||
description='The West Sound Community Hall was constructed. Funds for building materials were donated by George Adkins. The Hall was constructed by Adkins, Omer Freel, Joe Verrier, Peter LaPlante, Gus Smedberg and others. Mr. Adkins, who moved to West Sound in 1896, founded the West Sound Trading Company which was located on a wharf opposite the Hall.'
|
||||
title="1902 - 1903"
|
||||
description="The West Sound Community Hall was constructed. Funds for building materials were donated by George Adkins. The Hall was constructed by Adkins, Omer Freel, Joe Verrier, Peter LaPlante, Gus Smedberg and others. Mr. Adkins, who moved to West Sound in 1896, founded the West Sound Trading Company which was located on a wharf opposite the Hall."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1904'
|
||||
description='The Chase brothers, who owned the Chase Bros. Mill in West Sound, donated lumber and built an addition for a stage on the north end of the Hall.'
|
||||
title="1904"
|
||||
description="The Chase brothers, who owned the Chase Bros. Mill in West Sound, donated lumber and built an addition for a stage on the north end of the Hall."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1903 - 1935'
|
||||
description='During this period the following organizations were regular users of the Hall:'
|
||||
title="1903 - 1935"
|
||||
description="During this period the following organizations were regular users of the Hall:"
|
||||
>
|
||||
<div className="relative z-10 ml-4 mt-2 text-sm text-zinc-600">
|
||||
<DateListItem
|
||||
year='1903'
|
||||
value='Women's Christian Temperance Union Woodmen Lodge'
|
||||
year="1903"
|
||||
value="Women's Christian Temperance Union Woodmen Lodge"
|
||||
/>
|
||||
<DateListItem value="West Sound Literary Society" />
|
||||
<DateListItem year="1911" value="West Sound Boy's Band" />
|
||||
<DateListItem
|
||||
value='West Sound Literary Society'
|
||||
/>
|
||||
<DateListItem
|
||||
year='1911'
|
||||
value='West Sound Boy's Band'
|
||||
/>
|
||||
<DateListItem
|
||||
year='1912'
|
||||
value='West Sound Grange (130 members in 1913)'
|
||||
/>
|
||||
<DateListItem
|
||||
value='Odd Fellows'
|
||||
/>
|
||||
<DateListItem
|
||||
value='West Sound Athletic Club'
|
||||
/>
|
||||
<DateListItem
|
||||
year='1913'
|
||||
value='West Sound Orchestra'
|
||||
/>
|
||||
<DateListItem
|
||||
value='West Sound Baseball Team'
|
||||
/>
|
||||
<DateListItem
|
||||
year='1922'
|
||||
value='Farm Bureau'
|
||||
/>
|
||||
<DateListItem
|
||||
year='1925'
|
||||
value='Fidelis Circle'
|
||||
year="1912"
|
||||
value="West Sound Grange (130 members in 1913)"
|
||||
/>
|
||||
<DateListItem value="Odd Fellows" />
|
||||
<DateListItem value="West Sound Athletic Club" />
|
||||
<DateListItem year="1913" value="West Sound Orchestra" />
|
||||
<DateListItem value="West Sound Baseball Team" />
|
||||
<DateListItem year="1922" value="Farm Bureau" />
|
||||
<DateListItem year="1925" value="Fidelis Circle" />
|
||||
</div>
|
||||
</TimelineEntry>
|
||||
<TimelineEntry
|
||||
title='1905 - 1910'
|
||||
description='Sometime during this period the Hall was increased in size by adding twelve feet to the south end.'
|
||||
title="1905 - 1910"
|
||||
description="Sometime during this period the Hall was increased in size by adding twelve feet to the south end."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1935'
|
||||
description='West Sound Hall Company is reorganized as the West Sound Community Club.'
|
||||
title="1935"
|
||||
description="West Sound Hall Company is reorganized as the West Sound Community Club."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='Sometime after 1935'
|
||||
title="Sometime after 1935"
|
||||
description='The stage, then located at the north end of the hall, was remodeled " to make it as wide as the Hall and 22 feet back providing room for stage, kitchen and rest room - cost $122.85." Logs were salvaged from local beaches and the Thatcher Mill sawed them into lumber for use in remodel.'
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1940's'
|
||||
description='During the Second World War, Fidelis Circle cared for and managed the Hall.'
|
||||
title="1940's"
|
||||
description="During the Second World War, Fidelis Circle cared for and managed the Hall."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='Sometime after 1947'
|
||||
description='When it was determined the foundation under the stage was failing, the stage was converted to a kitchen and the floor was lowered to match the level of the main Hall floor. The current stage on the east side of the Hall was probably added at the same time.'
|
||||
title="Sometime after 1947"
|
||||
description="When it was determined the foundation under the stage was failing, the stage was converted to a kitchen and the floor was lowered to match the level of the main Hall floor. The current stage on the east side of the Hall was probably added at the same time."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1956'
|
||||
description='The Orcas Island Yacht Club was founded and began using the Hall as a clubhouse.'
|
||||
title="1956"
|
||||
description="The Orcas Island Yacht Club was founded and began using the Hall as a clubhouse."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1957'
|
||||
description='The south entry was moved to the present location on the east side of the Hall. The old entry and scaffolding for the new entry are shown in a photo taken in April 1957. This is the only known photo showing in detail how the exterior of the Hall looked prior to 1957.'
|
||||
title="1957"
|
||||
description="The south entry was moved to the present location on the east side of the Hall. The old entry and scaffolding for the new entry are shown in a photo taken in April 1957. This is the only known photo showing in detail how the exterior of the Hall looked prior to 1957."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1972'
|
||||
description='Members of the Orcas Island Yacht Club made major repairs to the building structure and the interior was completely remodeled. Prior to the remodel the interior walls were burlap cloth and there was no ceiling in the hall.'
|
||||
title="1972"
|
||||
description="Members of the Orcas Island Yacht Club made major repairs to the building structure and the interior was completely remodeled. Prior to the remodel the interior walls were burlap cloth and there was no ceiling in the hall."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1979'
|
||||
description='The property on which the hall sits was increased in size by donation a strip of land surrounding the hall structure.'
|
||||
title="1979"
|
||||
description="The property on which the hall sits was increased in size by donation a strip of land surrounding the hall structure."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1981'
|
||||
description='Major foundation repairs of a temporary nature were made.'
|
||||
title="1981"
|
||||
description="Major foundation repairs of a temporary nature were made."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1996'
|
||||
description='The entry stairs and deck were rebuilt.'
|
||||
title="1996"
|
||||
description="The entry stairs and deck were rebuilt."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1999'
|
||||
description='Realizing a major renovation of the Hall was needed, the officers of the West Sound Community Club reorganized the club as a nonprofit corporation and applied for 501(c)(3) status. A Centennial Building Committee was created to manage the renovation. The goal was to complete the renovation prior to the 100th anniversary of the Hall&appos;s construction in 1902. Con Russell Construction was selected as the contractor and construction started in February 2000. Major repairs, including a new foundation, metal roof, insulation, and painting the exterior, were completed by October of 2000. To date, the Club has received contributions and pledges of more than $81,000 to pay for the renovation and establish an endowment for future maintenance of the Hall.'
|
||||
title="1999"
|
||||
description="Realizing a major renovation of the Hall was needed, the officers of the West Sound Community Club reorganized the club as a nonprofit corporation and applied for 501(c)(3) status. A Centennial Building Committee was created to manage the renovation. The goal was to complete the renovation prior to the 100th anniversary of the Hall&appos;s construction in 1902. Con Russell Construction was selected as the contractor and construction started in February 2000. Major repairs, including a new foundation, metal roof, insulation, and painting the exterior, were completed by October of 2000. To date, the Club has received contributions and pledges of more than $81,000 to pay for the renovation and establish an endowment for future maintenance of the Hall."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='1999 - October 18th'
|
||||
description='The West Sound Community Hall was listed in the Washington Heritage Register.'
|
||||
title="1999 - October 18th"
|
||||
description="The West Sound Community Hall was listed in the Washington Heritage Register."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='2000 - June 12th'
|
||||
title="2000 - June 12th"
|
||||
description='The Washington Department of Revenue approved the West Sound Community Club's application for property tax exemption for the West Sound Community Hall as a "public assembly hall".'
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='2000 - August 31st'
|
||||
description='West Sound Community Hall web site first launched.'
|
||||
title="2000 - August 31st"
|
||||
description="West Sound Community Hall web site first launched."
|
||||
/>
|
||||
<TimelineEntry
|
||||
title='2001 - April 21st'
|
||||
title="2001 - April 21st"
|
||||
description='A new "West Sound Community Hall" sign was placed on the front of the Hall in a ceremony attended by more than twenty members of the West Sound Community Club. Placement of the sign marked the completion of a major renovation of the Hall started in February 2000.'
|
||||
/>
|
||||
<TimelineEntry title="2018" description="The hall is repainted" />
|
||||
<TimelineEntry
|
||||
title="2025"
|
||||
description="Various repairs and maintenance are performed including residing the North exterior wall. The well is found to contain ecoli and the board of directors begins working on hooking up to West Sound Water Association."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:pl-20">
|
||||
@ -271,5 +246,5 @@ export default function About() {
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ArticleLayout } from '@/components/ArticleLayout'
|
||||
import Image from 'next/image'
|
||||
import {MdxImage as Image } from '@/components/MdxImage'
|
||||
import boddingtonStore from './Boddingtons_Store_West_Sound.jpg'
|
||||
import westSoundMainStreet from './West_Sound_Main_Street.jpg'
|
||||
import westSound from './West_Sound.jpg'
|
||||
@ -8,7 +8,7 @@ export const article = {
|
||||
author: 'Tony Grosinger',
|
||||
date: '2024-02-17',
|
||||
title: 'February 2024 Potluck',
|
||||
description: "The second potluck of the year, with a slidshow of Orcas history from John Wachter.",
|
||||
description: "The second potluck of the year, with a slideshow of Orcas history from John Wachter.",
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ArticleLayout } from '@/components/ArticleLayout'
|
||||
import Image from 'next/image'
|
||||
import {MdxImage as Image } from '@/components/MdxImage'
|
||||
import townHallMeeting from './town-hall-meeting.jpg'
|
||||
|
||||
export const article = {
|
||||
|
BIN
src/app/news/2024-09-21-potluck/Land_Bank_Presentation.jpg
Normal file
After Width: | Height: | Size: 4.2 MiB |
54
src/app/news/2024-09-21-potluck/page.mdx
Normal file
@ -0,0 +1,54 @@
|
||||
import { ArticleLayout } from '@/components/ArticleLayout'
|
||||
import {MdxImage as Image } from '@/components/MdxImage'
|
||||
import landBankPresentation from './Land_Bank_Presentation.jpg'
|
||||
|
||||
export const article = {
|
||||
author: 'Tony Grosinger',
|
||||
date: '2024-09-21',
|
||||
title: 'September 2024 Potluck',
|
||||
description: "Our first potluck after the summer break, with Board of Director nominations for the election next month.",
|
||||
}
|
||||
|
||||
|
||||
export const metadata = {
|
||||
title: article.title,
|
||||
description: article.description,
|
||||
}
|
||||
|
||||
export default (props) => <ArticleLayout article={article} {...props} />
|
||||
|
||||
Summer is wrapping up and the monthly potlucks at the West Sound Hall have
|
||||
returned! There are several exciting developments to share with you. Here's a
|
||||
quick update on what was discussed at our recent community potluck:
|
||||
|
||||
In October, a contractor will be repairing the north end of the hall using the
|
||||
funds we raised earlier this year with Give Orcas.
|
||||
|
||||
Also in October, we will be electing the new Board of Directors. Our nominating
|
||||
committee - Cathy and Grant - have announced the slate of candidates. This
|
||||
year's nominees are:
|
||||
|
||||
- Lisa Pedersen for President
|
||||
- Betsy Wareham for Vice President
|
||||
- Beth Gasser for Secretary
|
||||
- Tony Grosinger for Treasurer
|
||||
- Leslie Brown for Director 1
|
||||
- Linn Hulley for Director 2
|
||||
|
||||
No additional nominations were made from the floor during the meeting. We
|
||||
encourage all members to join us at the October 19th potluck to vote for the
|
||||
new board.
|
||||
|
||||
<div className="not-prose flex flex-col items-center">
|
||||
<Image src={landBankPresentation} alt="Lincoln Bormann from the SJC Land Bank presenting at the potluck." />
|
||||
<span className="mt-2 text-sm text-zinc-400">
|
||||
Lincoln Bormann from the SJC Land Bank presenting at the potluck.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
After the potluck dinner, Lincoln Bormann and Brian Wiese from the San Juan
|
||||
County Land Bank gave a presentation outlining the work they do, how they make
|
||||
decisions about what land to acquire, and provided updates for newly opening
|
||||
parks. The Land Bank will be up for election this fall and you can learn more
|
||||
on their website - https://sjclandbank.org.
|
||||
|
BIN
src/app/news/2024-10-20-elections/N_Wall_Lower.jpg
Normal file
After Width: | Height: | Size: 239 KiB |
BIN
src/app/news/2024-10-20-elections/N_Wall_Upper.jpg
Normal file
After Width: | Height: | Size: 245 KiB |
44
src/app/news/2024-10-20-elections/page.mdx
Normal file
@ -0,0 +1,44 @@
|
||||
import { ArticleLayout } from '@/components/ArticleLayout'
|
||||
import {MdxImage as Image } from '@/components/MdxImage'
|
||||
import wallUpper from './N_Wall_Upper.jpg'
|
||||
import wallLower from './N_Wall_Lower.jpg'
|
||||
|
||||
export const article = {
|
||||
author: 'Tony Grosinger',
|
||||
date: '2024-10-20',
|
||||
title: 'Election and Building Repairs',
|
||||
description: "Board of director elections took place, as well as some updates on building maintenance.",
|
||||
}
|
||||
|
||||
|
||||
export const metadata = {
|
||||
title: article.title,
|
||||
description: article.description,
|
||||
}
|
||||
|
||||
export default (props) => <ArticleLayout article={article} {...props} />
|
||||
|
||||
At the October potluck we accepted votes for the 2024-2025 Board of Directors. Between those present and votes emailed prior to the potluck, we had enough participants to make a quorum and approve the slate.
|
||||
|
||||
There are also several new updates related to hall maintenance. First, repairs to the north wall ar under way! This maintenance work was made possible by generous donations during the Spring Give Orcas campaign where we raised $10,000.
|
||||
|
||||
<div className="not-prose flex flex-col items-center">
|
||||
<Image src={wallUpper} alt="Repairs to the upper portion of the north wall." />
|
||||
<span className="mt-2 text-sm text-zinc-400">
|
||||
Repairs to the upper portion of the north wall.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="not-prose flex flex-col items-center">
|
||||
<Image src={wallLower} alt="Repairs to the lower portion of the north wall." />
|
||||
<span className="mt-2 text-sm text-zinc-400">
|
||||
Repairs to the lower portion of the north wall.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
By the end of the month this wall should have brand new siding that will keep out the rain and breeze.
|
||||
|
||||
We also learned this month that our well water is not potable. After working with multiple experts and performing several rounds of chlorination treatment of the well and storage tanks, it has been determined that the best route forward is likely to abandon this water system and to move towards joining West Sound Water Association.
|
||||
|
||||
There is still lots of discussion and planning necessary before we can even break ground on making the hook up, but every party is working very hard to restore drinkable water to the hall as soon as possible!
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ArticleLayout } from '@/components/ArticleLayout'
|
||||
import Image from 'next/image'
|
||||
import {MdxImage as Image } from '@/components/MdxImage'
|
||||
import originalWebsite from './westsoundhall-original-website.png'
|
||||
|
||||
export const article = {
|
||||
|
123
src/app/page.tsx
@ -1,46 +1,43 @@
|
||||
import Image from 'next/image'
|
||||
|
||||
import Link from 'next/link'
|
||||
import { Card } from '@/components/Card'
|
||||
import { Container } from '@/components/Container'
|
||||
import { CalendarDaysIcon } from '@heroicons/react/24/solid'
|
||||
import exteriorFrontImage from '@/images/photos/exterior-front.png'
|
||||
import { type BlogPostWithSlug, getAllBlogPosts } from '@/lib/articles'
|
||||
import { formatDate } from '@/lib/formatDate'
|
||||
import { getUpcomingEvents, Event } from './calendar/page'
|
||||
import dayjs from 'dayjs'
|
||||
import Image from 'next/image';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { Card } from '@/components/Card';
|
||||
import { Container } from '@/components/Container';
|
||||
import { CalendarDaysIcon } from '@heroicons/react/24/solid';
|
||||
import exteriorFrontImage from '@/images/photos/exterior-front.png';
|
||||
import { type BlogPostWithSlug, getAllBlogPosts } from '@/lib/articles';
|
||||
import { formatDate } from '@/lib/formatDate';
|
||||
import { getUpcomingEvents, Event } from './calendar/page';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
function LinkButton({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string
|
||||
children: React.ReactNode
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="rounded-md px-3 py-2 font-semibold text-center transition bg-sky-300 hover:bg-sky-400"
|
||||
className="rounded-md bg-sky-300 px-3 py-2 text-center font-semibold transition hover:bg-sky-400"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function Article({ article }: { article: BlogPostWithSlug }) {
|
||||
return (
|
||||
<Card as="article">
|
||||
<Card.Title href={`/news/${article.slug}`}>
|
||||
{article.title}
|
||||
</Card.Title>
|
||||
<Card.Title href={`/news/${article.slug}`}>{article.title}</Card.Title>
|
||||
<Card.Eyebrow as="time" dateTime={article.date} decorate>
|
||||
{formatDate(article.date)}
|
||||
</Card.Eyebrow>
|
||||
<Card.Description>{article.description}</Card.Description>
|
||||
<Card.Cta>Read article</Card.Cta>
|
||||
</Card>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function EventListItem({ event }: { event: Event }) {
|
||||
@ -57,40 +54,40 @@ function EventListItem({ event }: { event: Event }) {
|
||||
{event.name}
|
||||
</dd>
|
||||
<dt className="sr-only">Date</dt>
|
||||
<dd className="text-xs text-zinc-500">
|
||||
{date}
|
||||
</dd>
|
||||
<dd className="text-xs text-zinc-500">{date}</dd>
|
||||
<dt className="sr-only">Time</dt>
|
||||
{event.allDay
|
||||
? <dd
|
||||
className="ml-auto text-xs text-zinc-400"
|
||||
aria-label="All day"
|
||||
>
|
||||
{event.allDay ? (
|
||||
<dd className="ml-auto text-xs text-zinc-400" aria-label="All day">
|
||||
All day
|
||||
</dd>
|
||||
: (event.end
|
||||
? (
|
||||
<dd
|
||||
className="ml-auto text-xs text-zinc-400"
|
||||
aria-label={`${start.format('YYYY-MM-DD HH:mm')} until ${end.format('YYYY-MM-DD HH-mm')}`}
|
||||
>
|
||||
<time dateTime={start.format('YYYY-MM-DD HH:mm')}>{start.format('h:mm a')}</time>{' '}
|
||||
<span aria-hidden="true">—</span>{' '}
|
||||
<time dateTime={end.format('YYYY-MM-DD HH-mm')}>{end.format('h:mm a')}</time>{' '}
|
||||
</dd>
|
||||
) : (
|
||||
<dd
|
||||
className="ml-auto text-xs text-zinc-400"
|
||||
aria-label={start.format('YYYY-MM-DD HH-mm')}
|
||||
>
|
||||
<time dateTime={start.format('YYYY-MM-DD HH-mm')}>{start.format('h:mm a')}</time>{' '}
|
||||
</dd>
|
||||
)
|
||||
)
|
||||
}
|
||||
) : event.end ? (
|
||||
<dd
|
||||
className="ml-auto text-xs text-zinc-400"
|
||||
aria-label={`${start.format('YYYY-MM-DD HH:mm')} until ${end.format(
|
||||
'YYYY-MM-DD HH-mm',
|
||||
)}`}
|
||||
>
|
||||
<time dateTime={start.format('YYYY-MM-DD HH:mm')}>
|
||||
{start.format('h:mm a')}
|
||||
</time>{' '}
|
||||
<span aria-hidden="true">—</span>{' '}
|
||||
<time dateTime={end.format('YYYY-MM-DD HH-mm')}>
|
||||
{end.format('h:mm a')}
|
||||
</time>{' '}
|
||||
</dd>
|
||||
) : (
|
||||
<dd
|
||||
className="ml-auto text-xs text-zinc-400"
|
||||
aria-label={start.format('YYYY-MM-DD HH-mm')}
|
||||
>
|
||||
<time dateTime={start.format('YYYY-MM-DD HH-mm')}>
|
||||
{start.format('h:mm a')}
|
||||
</time>{' '}
|
||||
</dd>
|
||||
)}
|
||||
</dl>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async function Events() {
|
||||
@ -113,40 +110,44 @@ async function Events() {
|
||||
</Button>
|
||||
*/}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default async function Home() {
|
||||
let articles = (await getAllBlogPosts()).slice(0, 4)
|
||||
let articles = (await getAllBlogPosts()).slice(0, 4);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mx-auto max-w-7xl px-6 mt-24 lg:px-8">
|
||||
<div className="mx-auto mt-24 max-w-7xl px-6 lg:px-8">
|
||||
<div className="relative px-4 sm:px-8 lg:px-12">
|
||||
<div className="mx-auto max-w-2xl lg:mx-0 grid lg:max-w-none grid-cols-1 lg:grid-cols-2 lg:gap-x-8 gap-y-10">
|
||||
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-y-10 lg:mx-0 lg:max-w-none lg:grid-cols-2 lg:gap-x-8">
|
||||
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 sm:text-6xl lg:col-span-2">
|
||||
West Sound Community Hall
|
||||
</h1>
|
||||
<div className="max-w-xl">
|
||||
<p className="mt-6 text-base text-zinc-600">
|
||||
The West Sound Community Hall is located in the hamlet of West Sound
|
||||
on Orcas Island, about 10 minutes from the ferry landing and
|
||||
Eastsound. It has served as a public assembly hall since it was
|
||||
built by volunteers in 1902.
|
||||
The West Sound Community Hall is located in the hamlet of West
|
||||
Sound on Orcas Island, about 10 minutes from the ferry landing
|
||||
and Eastsound. It has served as a public assembly hall since it
|
||||
was built by volunteers in 1902.
|
||||
</p>
|
||||
<p className="mt-6 text-base text-zinc-600">
|
||||
Facing West Sound, the Hall is at the heart of the West Sound community.
|
||||
Facing West Sound, the Hall is at the heart of the West Sound
|
||||
community.
|
||||
</p>
|
||||
</div>
|
||||
<Image
|
||||
src={exteriorFrontImage}
|
||||
alt="Exterior front of the West Sound Hall"
|
||||
className="lg:row-span-2 w-full max-w-xl rounded-2xl object-cover lg:max-w-none"
|
||||
className="w-full max-w-xl rounded-2xl object-cover lg:row-span-2 lg:max-w-none"
|
||||
/>
|
||||
<div className="h-fit max-w-xl rounded-2xl border border-zinc-100 p-6">
|
||||
<div className="flex flex-col gap-y-4">
|
||||
<LinkButton href='/club'>Join or Renew your Membership</LinkButton>
|
||||
<LinkButton href='/rental'>Rent the Hall</LinkButton>
|
||||
<LinkButton href="/club">
|
||||
Join or Renew your Membership
|
||||
</LinkButton>
|
||||
<LinkButton href="/donate">Donate</LinkButton>
|
||||
<LinkButton href="/rental">Rent the Hall</LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -165,5 +166,5 @@ export default async function Home() {
|
||||
</div>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,99 +0,0 @@
|
||||
import { type Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
|
||||
import { Card } from '@/components/Card'
|
||||
import { SimpleLayout } from '@/components/SimpleLayout'
|
||||
import logoAnimaginary from '@/images/logos/animaginary.svg'
|
||||
import logoCosmos from '@/images/logos/cosmos.svg'
|
||||
import logoHelioStream from '@/images/logos/helio-stream.svg'
|
||||
import logoOpenShuttle from '@/images/logos/open-shuttle.svg'
|
||||
import logoPlanetaria from '@/images/logos/planetaria.svg'
|
||||
|
||||
const projects = [
|
||||
{
|
||||
name: 'Planetaria',
|
||||
description:
|
||||
'Creating technology to empower civilians to explore space on their own terms.',
|
||||
link: { href: 'http://planetaria.tech', label: 'planetaria.tech' },
|
||||
logo: logoPlanetaria,
|
||||
},
|
||||
{
|
||||
name: 'Animaginary',
|
||||
description:
|
||||
'High performance web animation library, hand-written in optimized WASM.',
|
||||
link: { href: '#', label: 'github.com' },
|
||||
logo: logoAnimaginary,
|
||||
},
|
||||
{
|
||||
name: 'HelioStream',
|
||||
description:
|
||||
'Real-time video streaming library, optimized for interstellar transmission.',
|
||||
link: { href: '#', label: 'github.com' },
|
||||
logo: logoHelioStream,
|
||||
},
|
||||
{
|
||||
name: 'cosmOS',
|
||||
description:
|
||||
'The operating system that powers our Planetaria space shuttles.',
|
||||
link: { href: '#', label: 'github.com' },
|
||||
logo: logoCosmos,
|
||||
},
|
||||
{
|
||||
name: 'OpenShuttle',
|
||||
description:
|
||||
'The schematics for the first rocket I designed that successfully made it to orbit.',
|
||||
link: { href: '#', label: 'github.com' },
|
||||
logo: logoOpenShuttle,
|
||||
},
|
||||
]
|
||||
|
||||
function LinkIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
|
||||
<path
|
||||
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Projects',
|
||||
description: 'Things I’ve made trying to put my dent in the universe.',
|
||||
}
|
||||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<SimpleLayout
|
||||
title="Things I’ve made trying to put my dent in the universe."
|
||||
intro="I’ve worked on tons of little projects over the years but these are the ones that I’m most proud of. Many of them are open-source, so if you see something that piques your interest, check out the code and contribute if you have ideas for how it can be improved."
|
||||
>
|
||||
<ul
|
||||
role="list"
|
||||
className="grid grid-cols-1 gap-x-12 gap-y-16 sm:grid-cols-2 lg:grid-cols-3"
|
||||
>
|
||||
{projects.map((project) => (
|
||||
<Card as="li" key={project.name}>
|
||||
<div className="relative z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5">
|
||||
<Image
|
||||
src={project.logo}
|
||||
alt=""
|
||||
className="h-8 w-8"
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
<h2 className="mt-6 text-base font-semibold text-zinc-800">
|
||||
<Card.Link href={project.link.href}>{project.name}</Card.Link>
|
||||
</h2>
|
||||
<Card.Description>{project.description}</Card.Description>
|
||||
<p className="relative z-10 mt-6 flex text-sm font-medium text-zinc-400 transition group-hover:text-teal-500">
|
||||
<LinkIcon className="h-6 w-6 flex-none" />
|
||||
<span className="ml-2">{project.link.label}</span>
|
||||
</p>
|
||||
</Card>
|
||||
))}
|
||||
</ul>
|
||||
</SimpleLayout>
|
||||
)
|
||||
}
|
@ -34,7 +34,7 @@ function SocialLink({
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'West Sound Hall Rental',
|
||||
title: 'Hall Rental',
|
||||
description:
|
||||
'Rental information for the West Sound Hall.',
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
import { type Metadata } from 'next'
|
||||
import { type Metadata } from 'next';
|
||||
|
||||
import { SimpleLayout } from '@/components/SimpleLayout'
|
||||
import { SimpleLayout } from '@/components/SimpleLayout';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Thank You',
|
||||
description: 'Thanks for becoming a member.',
|
||||
}
|
||||
};
|
||||
|
||||
export default async function ThankYou({
|
||||
searchParams
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: { [key: string]: string | string[] | undefined }
|
||||
searchParams: { [key: string]: string | string[] | undefined };
|
||||
}) {
|
||||
|
||||
const { redirect_status } = searchParams;
|
||||
if (redirect_status !== 'succeeded') {
|
||||
// TODO: Display error
|
||||
@ -23,9 +22,11 @@ export default async function ThankYou({
|
||||
title="Thanks for becoming a member."
|
||||
intro="Thank you for joining the West Sound Community Club."
|
||||
>
|
||||
<p className="mt-6 text-base text-zinc-600">
|
||||
Your financial support helps us perserve this historic building and to host events for the community. We'll add you to our member mailing list so you receive announcement emails about upcoming events.
|
||||
<p className="text-base text-zinc-600">
|
||||
Your financial support helps us perserve this historic building and to
|
||||
host events for the community. We'll add you to our member mailing
|
||||
list so you receive announcement emails about upcoming events.
|
||||
</p>
|
||||
</SimpleLayout>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
7
src/components/MdxImage.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
import Image, { ImageProps } from 'next/image'
|
||||
|
||||
// Workaround for https://github.com/hashicorp/next-mdx-remote/issues/405
|
||||
export function MdxImage(props: ImageProps) {
|
||||
return <Image {...props} alt={props.alt} />;
|
||||
}
|
BIN
src/images/logo.png
Normal file
After Width: | Height: | Size: 91 KiB |
@ -1,12 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="16" cy="16" r="16" fill="url(#a)"/>
|
||||
<rect x="16" y="8" width="8" height="8" rx="2" fill="#fff" fill-opacity=".4"/>
|
||||
<rect x="12" y="12" width="8" height="8" rx="2" fill="#fff" fill-opacity=".5"/>
|
||||
<rect x="8" y="16" width="8" height="8" rx="2" fill="#fff"/>
|
||||
<defs>
|
||||
<radialGradient id="a" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 18.5 -18.5 0 16 13.5)">
|
||||
<stop offset=".169" stop-color="#22D3EE"/>
|
||||
<stop offset="1" stop-color="#7451FF"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 625 B |
@ -1,25 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#a)">
|
||||
<rect width="32" height="32" rx="16" fill="#001120"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 13a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1h-2Zm-3 1a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v4a3 3 0 0 1-3 3h-2a3 3 0 0 1-3-3v-4Zm10-.257A2.743 2.743 0 0 1 19.743 11H22a3 3 0 0 1 3 3 1 1 0 1 1-2 0 1 1 0 0 0-1-1h-2.257a.743.743 0 0 0-.235 1.449l3.616 1.205A2.743 2.743 0 0 1 22.257 21H20a3 3 0 0 1-3-3 1 1 0 1 1 2 0 1 1 0 0 0 1 1h2.257a.743.743 0 0 0 .235-1.449l-3.616-1.205A2.743 2.743 0 0 1 17 13.743Z" fill="url(#b)"/>
|
||||
<path fill="#fff" fill-opacity=".1" d="M0 23h32v1H0z"/>
|
||||
<path fill="#fff" fill-opacity=".1" d="M5 0v32H4V0z"/>
|
||||
<path fill="#fff" fill-opacity=".1" d="M0 8h32v1H0z"/>
|
||||
<path fill="url(#c)" d="M0 23h32v1H0z"/>
|
||||
<path fill="#fff" fill-opacity=".1" d="M28 0v32h-1V0z"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="b" x1="11" y1="12" x2="11" y2="20" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff"/>
|
||||
<stop offset="1" stop-color="#E3E8ED"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" x1="1.5" y1="23.5" x2="30.5" y2="23.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff" stop-opacity="0"/>
|
||||
<stop offset=".486" stop-color="#fff"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<clipPath id="a">
|
||||
<rect width="32" height="32" rx="16" fill="#fff"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,5 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="32" height="32" rx="16" fill="#F43F5E" />
|
||||
<path d="M9 11a2 2 0 0 1 2-2h2v12a2 2 0 0 1-2 2H9V11ZM19 11a2 2 0 0 1 2-2h2v12a2 2 0 0 1-2 2h-2V11Z" fill="#fff" />
|
||||
<path d="M15.447 16.106A2 2 0 0 1 17.237 15H21v2h-6l.447-.894Z" fill="#fff" />
|
||||
</svg>
|
Before Width: | Height: | Size: 339 B |
@ -1,21 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#a)">
|
||||
<rect width="32" height="32" rx="16" fill="#0085FF" />
|
||||
<path fill="#fff" fill-opacity=".2" d="M0 26h32v1H0z" />
|
||||
<path fill="#fff" fill-opacity=".2" d="M8 0v32H7V0zM16.5 0v32h-1V0z" />
|
||||
<path fill="#fff" fill-opacity=".2" d="M0 5h32v1H0zM0 15.5h32v1H0z" />
|
||||
<path fill="#fff" fill-opacity=".2" d="M25 0v32h-1V0z" />
|
||||
<path
|
||||
d="M13 21v-5.485c0-2.959-.228-4.866 1.24-7.435l.892-1.56a1 1 0 0 1 1.736 0l.892 1.56C19.228 10.65 19 12.556 19 15.515V21l3.293 3.293c.63.63.184 1.707-.707 1.707H10.414c-.89 0-1.337-1.077-.707-1.707L13 21Z"
|
||||
fill="#fff" />
|
||||
<path
|
||||
d="M13 26v-5m0 5h6m-6 0h-2.586c-.89 0-1.337-1.077-.707-1.707L13 21m0 0v-5.485c0-2.959-.228-4.866 1.24-7.435l.892-1.56a1 1 0 0 1 1.736 0l.892 1.56C19.228 10.65 19 12.556 19 15.515V21m0 5h2.586c.89 0 1.337-1.077.707-1.707L19 21m0 5v-5"
|
||||
stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M16 13v2" stroke="#0085FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<rect width="32" height="32" rx="16" fill="#fff" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,24 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#a)">
|
||||
<rect width="32" height="32" rx="16" fill="url(#b)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.755 30.136c.051-4.308.484-8.167 1.147-10.985.355-1.509.766-2.677 1.196-3.45.466-.838.801-.951.902-.951.1 0 .436.113.902.95.43.774.841 1.942 1.196 3.451.663 2.818 1.096 6.677 1.147 10.985.508-.117 1.007-.26 1.494-.428-.074-4.224-.508-8.042-1.18-10.9-.327-1.389-.718-2.584-1.169-3.497 1.498.715 2.887 2.097 4.035 4.048 1.257 2.138 2.179 4.894 2.589 8 .47-.374.916-.775 1.335-1.203-.488-2.878-1.402-5.467-2.631-7.557-.652-1.107-1.402-2.09-2.236-2.901a16.296 16.296 0 0 1 7.851 6.01c.236-.55.439-1.117.606-1.699C26.688 15.892 21.653 13.25 16 13.25c-5.653 0-10.688 2.642-13.939 6.759.167.582.37 1.15.606 1.7a16.295 16.295 0 0 1 7.85-6.011c-.833.811-1.583 1.794-2.235 2.9-1.23 2.091-2.143 4.68-2.631 7.558.42.428.866.83 1.335 1.203.41-3.106 1.332-5.862 2.59-8 1.147-1.95 2.536-3.333 4.034-4.048-.451.913-.842 2.108-1.168 3.496-.673 2.86-1.107 6.677-1.18 10.901.486.168.984.311 1.493.428Zm-.002 1.534a15.857 15.857 0 0 1-1.502-.387c.017 4.623.465 8.825 1.19 11.91.327 1.388.718 2.583 1.169 3.496-1.498-.715-2.887-2.097-4.035-4.048C7.845 39.698 6.75 35.584 6.75 31c0-.643.022-1.276.063-1.899a16.074 16.074 0 0 1-1.41-1.113c-.1.98-.153 1.986-.153 3.012 0 4.804 1.144 9.19 3.032 12.401.652 1.107 1.402 2.09 2.236 2.901C4.24 44.052-.25 38.051-.25 31c0-2.814.715-5.46 1.974-7.768a15.914 15.914 0 0 1-.741-1.699A17.667 17.667 0 0 0-1.75 31c0 9.803 7.947 17.75 17.75 17.75S33.75 40.803 33.75 31c0-3.48-1.002-6.727-2.733-9.467-.214.583-.462 1.15-.74 1.699A16.178 16.178 0 0 1 32.25 31c0 7.05-4.49 13.053-10.768 15.302.834-.811 1.584-1.794 2.236-2.9C25.605 40.19 26.75 35.803 26.75 31c0-1.026-.052-2.032-.152-3.012-.45.396-.92.768-1.411 1.113.041.623.063 1.256.063 1.899 0 4.584-1.095 8.698-2.825 11.64-1.148 1.952-2.537 3.334-4.035 4.049.451-.913.842-2.108 1.168-3.496.726-3.085 1.174-7.287 1.192-11.91-.492.153-.993.282-1.503.387-.04 4.386-.476 8.319-1.149 11.179-.355 1.509-.766 2.677-1.196 3.45-.466.838-.801.951-.902.951-.1 0-.436-.113-.902-.95-.43-.774-.841-1.942-1.196-3.451-.673-2.86-1.108-6.793-1.149-11.179Z" fill="url(#c)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.894 5.553a1 1 0 0 1-.447 1.342l-9.341 3.552c-.494.247.246.494 0 0-.247-.494-.494.247 0 0l8.447-5.341a1 1 0 0 1 1.341.447Z" fill="url(#d)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="b" x1="16" y1="0" x2="16" y2="33" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00172C"/>
|
||||
<stop offset=".803" stop-color="#5900EB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="d" x1="19" y1="6" x2="11.5" y2="10" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#9969E8"/>
|
||||
<stop offset="1" stop-color="#FFA0D2" stop-opacity=".32"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="c" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 35.75 -57.5 0 16 13)">
|
||||
<stop offset=".14" stop-color="#fff"/>
|
||||
<stop offset=".514" stop-color="#fff" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="a">
|
||||
<rect width="32" height="32" rx="16" fill="#fff"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.2 KiB |
@ -6,6 +6,8 @@ const serverToken = process.env.POSTMARK_SERVER_TOKEN || '';
|
||||
const client = new ServerClient(serverToken);
|
||||
|
||||
export function emailNotification({
|
||||
subject,
|
||||
bodyPrefix,
|
||||
name,
|
||||
type,
|
||||
amount,
|
||||
@ -13,6 +15,8 @@ export function emailNotification({
|
||||
phone,
|
||||
address,
|
||||
}: {
|
||||
subject: string;
|
||||
bodyPrefix: string;
|
||||
name: string;
|
||||
type: string;
|
||||
amount: number;
|
||||
@ -23,9 +27,9 @@ export function emailNotification({
|
||||
client.sendEmail({
|
||||
From: fromAddr,
|
||||
To: toAddr,
|
||||
Subject: 'New WSCC Membership',
|
||||
Subject: subject,
|
||||
TextBody: [
|
||||
'New WSCC member:',
|
||||
bodyPrefix,
|
||||
'',
|
||||
'Name: ' + name,
|
||||
'Type: ' + type,
|
||||
|