Merge pull request #36 from sambecker/auth-integration
Nav auth integration
This commit is contained in:
commit
756cbc7f1b
@ -17,10 +17,10 @@
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/node": "^20.10.6",
|
||||
"@types/react": "18.2.46",
|
||||
"@types/react": "18.2.47",
|
||||
"@types/react-dom": "18.2.18",
|
||||
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
||||
"@typescript-eslint/parser": "^6.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.0",
|
||||
"@typescript-eslint/parser": "^6.18.0",
|
||||
"@vercel/analytics": "^1.1.1",
|
||||
"@vercel/blob": "^0.16.1",
|
||||
"@vercel/postgres": "0.5.1",
|
||||
@ -44,7 +44,7 @@
|
||||
"react-dom": "18.2.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"sonner": "^1.3.1",
|
||||
"tailwindcss": "3.4.0",
|
||||
"tailwindcss": "3.4.1",
|
||||
"ts-exif-parser": "^0.2.2",
|
||||
"typescript": "5.3.3"
|
||||
}
|
||||
|
||||
126
pnpm-lock.yaml
generated
126
pnpm-lock.yaml
generated
@ -16,7 +16,7 @@ dependencies:
|
||||
version: 14.0.4
|
||||
'@tailwindcss/forms':
|
||||
specifier: ^0.5.7
|
||||
version: 0.5.7(tailwindcss@3.4.0)
|
||||
version: 0.5.7(tailwindcss@3.4.1)
|
||||
'@testing-library/jest-dom':
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0(@types/jest@29.5.11)(jest@29.7.0)
|
||||
@ -30,17 +30,17 @@ dependencies:
|
||||
specifier: ^20.10.6
|
||||
version: 20.10.6
|
||||
'@types/react':
|
||||
specifier: 18.2.46
|
||||
version: 18.2.46
|
||||
specifier: 18.2.47
|
||||
version: 18.2.47
|
||||
'@types/react-dom':
|
||||
specifier: 18.2.18
|
||||
version: 18.2.18
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^6.17.0
|
||||
version: 6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
specifier: ^6.18.0
|
||||
version: 6.18.0(@typescript-eslint/parser@6.18.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^6.17.0
|
||||
version: 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
specifier: ^6.18.0
|
||||
version: 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@vercel/analytics':
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
@ -111,8 +111,8 @@ dependencies:
|
||||
specifier: ^1.3.1
|
||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||
tailwindcss:
|
||||
specifier: 3.4.0
|
||||
version: 3.4.0
|
||||
specifier: 3.4.1
|
||||
version: 3.4.1
|
||||
ts-exif-parser:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
@ -2118,13 +2118,13 @@ packages:
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@tailwindcss/forms@0.5.7(tailwindcss@3.4.0):
|
||||
/@tailwindcss/forms@0.5.7(tailwindcss@3.4.1):
|
||||
resolution: {integrity: sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==}
|
||||
peerDependencies:
|
||||
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
|
||||
dependencies:
|
||||
mini-svg-data-uri: 1.4.4
|
||||
tailwindcss: 3.4.0
|
||||
tailwindcss: 3.4.1
|
||||
dev: false
|
||||
|
||||
/@testing-library/dom@9.3.3:
|
||||
@ -2289,11 +2289,11 @@ packages:
|
||||
/@types/react-dom@18.2.18:
|
||||
resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==}
|
||||
dependencies:
|
||||
'@types/react': 18.2.46
|
||||
'@types/react': 18.2.47
|
||||
dev: false
|
||||
|
||||
/@types/react@18.2.46:
|
||||
resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==}
|
||||
/@types/react@18.2.47:
|
||||
resolution: {integrity: sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.11
|
||||
'@types/scheduler': 0.16.8
|
||||
@ -2326,8 +2326,8 @@ packages:
|
||||
'@types/yargs-parser': 21.0.3
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/eslint-plugin@6.17.0(@typescript-eslint/parser@6.17.0)(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==}
|
||||
/@typescript-eslint/eslint-plugin@6.18.0(@typescript-eslint/parser@6.18.0)(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
|
||||
@ -2338,11 +2338,11 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.10.0
|
||||
'@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/scope-manager': 6.17.0
|
||||
'@typescript-eslint/type-utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/visitor-keys': 6.17.0
|
||||
'@typescript-eslint/parser': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/scope-manager': 6.18.0
|
||||
'@typescript-eslint/type-utils': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/utils': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/visitor-keys': 6.18.0
|
||||
debug: 4.3.4
|
||||
eslint: 8.56.0
|
||||
graphemer: 1.4.0
|
||||
@ -2355,8 +2355,8 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/parser@6.17.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==}
|
||||
/@typescript-eslint/parser@6.18.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
@ -2365,10 +2365,10 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 6.17.0
|
||||
'@typescript-eslint/types': 6.17.0
|
||||
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3)
|
||||
'@typescript-eslint/visitor-keys': 6.17.0
|
||||
'@typescript-eslint/scope-manager': 6.18.0
|
||||
'@typescript-eslint/types': 6.18.0
|
||||
'@typescript-eslint/typescript-estree': 6.18.0(typescript@5.3.3)
|
||||
'@typescript-eslint/visitor-keys': 6.18.0
|
||||
debug: 4.3.4
|
||||
eslint: 8.56.0
|
||||
typescript: 5.3.3
|
||||
@ -2376,16 +2376,16 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/scope-manager@6.17.0:
|
||||
resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==}
|
||||
/@typescript-eslint/scope-manager@6.18.0:
|
||||
resolution: {integrity: sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 6.17.0
|
||||
'@typescript-eslint/visitor-keys': 6.17.0
|
||||
'@typescript-eslint/types': 6.18.0
|
||||
'@typescript-eslint/visitor-keys': 6.18.0
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/type-utils@6.17.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==}
|
||||
/@typescript-eslint/type-utils@6.18.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
@ -2394,8 +2394,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3)
|
||||
'@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/typescript-estree': 6.18.0(typescript@5.3.3)
|
||||
'@typescript-eslint/utils': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
debug: 4.3.4
|
||||
eslint: 8.56.0
|
||||
ts-api-utils: 1.0.3(typescript@5.3.3)
|
||||
@ -2404,13 +2404,13 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/types@6.17.0:
|
||||
resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==}
|
||||
/@typescript-eslint/types@6.18.0:
|
||||
resolution: {integrity: sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/typescript-estree@6.17.0(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==}
|
||||
/@typescript-eslint/typescript-estree@6.18.0(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
@ -2418,8 +2418,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 6.17.0
|
||||
'@typescript-eslint/visitor-keys': 6.17.0
|
||||
'@typescript-eslint/types': 6.18.0
|
||||
'@typescript-eslint/visitor-keys': 6.18.0
|
||||
debug: 4.3.4
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
@ -2431,8 +2431,8 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/utils@6.17.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==}
|
||||
/@typescript-eslint/utils@6.18.0(eslint@8.56.0)(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
@ -2440,9 +2440,9 @@ packages:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
|
||||
'@types/json-schema': 7.0.15
|
||||
'@types/semver': 7.5.6
|
||||
'@typescript-eslint/scope-manager': 6.17.0
|
||||
'@typescript-eslint/types': 6.17.0
|
||||
'@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3)
|
||||
'@typescript-eslint/scope-manager': 6.18.0
|
||||
'@typescript-eslint/types': 6.18.0
|
||||
'@typescript-eslint/typescript-estree': 6.18.0(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
semver: 7.5.4
|
||||
transitivePeerDependencies:
|
||||
@ -2450,11 +2450,11 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
/@typescript-eslint/visitor-keys@6.17.0:
|
||||
resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==}
|
||||
/@typescript-eslint/visitor-keys@6.18.0:
|
||||
resolution: {integrity: sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 6.17.0
|
||||
'@typescript-eslint/types': 6.18.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
dev: false
|
||||
|
||||
@ -3476,11 +3476,11 @@ packages:
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 14.0.4
|
||||
'@rushstack/eslint-patch': 1.6.1
|
||||
'@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0)
|
||||
eslint-plugin-react: 7.33.2(eslint@8.56.0)
|
||||
eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0)
|
||||
@ -3500,7 +3500,7 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0):
|
||||
/eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0):
|
||||
resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -3510,8 +3510,8 @@ packages:
|
||||
debug: 4.3.4
|
||||
enhanced-resolve: 5.15.0
|
||||
eslint: 8.56.0
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.2
|
||||
is-core-module: 2.13.1
|
||||
@ -3523,7 +3523,7 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
|
||||
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
|
||||
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@ -3544,16 +3544,16 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
debug: 3.2.7
|
||||
eslint: 8.56.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@ -3563,7 +3563,7 @@ packages:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 6.17.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.18.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
array-includes: 3.1.7
|
||||
array.prototype.findlastindex: 1.2.3
|
||||
array.prototype.flat: 1.3.2
|
||||
@ -3572,7 +3572,7 @@ packages:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.56.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
|
||||
hasown: 2.0.0
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
@ -6305,8 +6305,8 @@ packages:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
dev: false
|
||||
|
||||
/tailwindcss@3.4.0:
|
||||
resolution: {integrity: sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA==}
|
||||
/tailwindcss@3.4.1:
|
||||
resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
import FooterAuth from '@/site/FooterAuth';
|
||||
import PageContentContainer from '@/components/PageContentContainer';
|
||||
import { SessionProvider } from 'next-auth/react';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<SessionProvider>
|
||||
<PageContentContainer>
|
||||
{children}
|
||||
</PageContentContainer>
|
||||
<FooterAuth />
|
||||
</SessionProvider>
|
||||
);
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import FooterStatic from '@/site/FooterStatic';
|
||||
import PageContentContainer from '@/components/PageContentContainer';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<PageContentContainer>
|
||||
{children}
|
||||
</PageContentContainer>
|
||||
<FooterStatic />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -9,6 +9,10 @@ import ThemeProviderClient from '@/site/ThemeProviderClient';
|
||||
import Nav from '@/site/Nav';
|
||||
import ToasterWithThemes from '@/toast/ToasterWithThemes';
|
||||
import PhotoEscapeHandler from '@/photo/PhotoEscapeHandler';
|
||||
import Footer from '@/site/Footer';
|
||||
import { Suspense } from 'react';
|
||||
import FooterClient from '@/site/FooterClient';
|
||||
import NavClient from '@/site/NavClient';
|
||||
|
||||
import '../site/globals.css';
|
||||
|
||||
@ -68,21 +72,31 @@ export default function RootLayout({
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<body className={ibmPlexMono.variable}>
|
||||
<StateProvider>
|
||||
<ThemeProviderClient>
|
||||
<main className={clsx(
|
||||
'px-3 pb-3',
|
||||
'lg:px-6 lg:pb-6',
|
||||
'mx-3 mb-3',
|
||||
'lg:mx-6 lg:mb-6',
|
||||
)}>
|
||||
<Suspense fallback={<NavClient />}>
|
||||
<Nav />
|
||||
<StateProvider>
|
||||
</Suspense>
|
||||
<div className={clsx(
|
||||
'min-h-[16rem] sm:min-h-[30rem]',
|
||||
'mb-12',
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
<Suspense fallback={<FooterClient />}>
|
||||
<Footer />
|
||||
</Suspense>
|
||||
</main>
|
||||
</ThemeProviderClient>
|
||||
</StateProvider>
|
||||
<Analytics />
|
||||
<SpeedInsights />
|
||||
</main>
|
||||
<PhotoEscapeHandler />
|
||||
<ToasterWithThemes />
|
||||
</ThemeProviderClient>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@ -9,7 +9,7 @@ export const signInAction = async (
|
||||
try {
|
||||
await signIn('credentials', Object.fromEntries(formData));
|
||||
} catch (error) {
|
||||
if ((error as Error).message.includes(CREDENTIALS_SIGN_IN_ERROR)) {
|
||||
if ((`${error}`).includes(CREDENTIALS_SIGN_IN_ERROR)) {
|
||||
return CREDENTIALS_SIGN_IN_ERROR;
|
||||
}
|
||||
throw error;
|
||||
|
||||
4
src/cache/index.ts
vendored
4
src/cache/index.ts
vendored
@ -28,6 +28,8 @@ import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
|
||||
import type { Session } from 'next-auth';
|
||||
import { createCameraKey } from '@/camera';
|
||||
import { PATHS_ADMIN } from '@/site/paths';
|
||||
import { cache } from 'react';
|
||||
import { auth } from '@/auth';
|
||||
|
||||
// Table key
|
||||
const KEY_PHOTOS = 'photos';
|
||||
@ -207,6 +209,8 @@ export const getUniqueFilmSimulationsCached =
|
||||
[KEY_PHOTOS, KEY_FILM_SIMULATIONS],
|
||||
);
|
||||
|
||||
export const authCached = cache(auth);
|
||||
|
||||
// No Store
|
||||
|
||||
export const getPhotoNoStore = (...args: Parameters<typeof getPhoto>) => {
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
export default function PageContentContainer({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="min-h-[16rem] sm:min-h-[30rem]">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -12,12 +12,15 @@ export default function RepoLink() {
|
||||
href="http://github.com/sambecker/exif-photo-blog"
|
||||
target="_blank"
|
||||
className={clsx(
|
||||
'flex items-center gap-1',
|
||||
'text-black dark:text-white',
|
||||
'flex items-center gap-0.5',
|
||||
'text-main hover:text-main',
|
||||
'hover:underline',
|
||||
)}
|
||||
>
|
||||
<BiLogoGithub className="translate-y-[1px] hidden xs:inline-block" />
|
||||
<BiLogoGithub
|
||||
size={16}
|
||||
className="translate-y-[0.5px] hidden xs:inline-block"
|
||||
/>
|
||||
exif-photo-blog
|
||||
</Link>
|
||||
</span>
|
||||
|
||||
9
src/site/Footer.tsx
Normal file
9
src/site/Footer.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import { authCached } from '@/cache';
|
||||
import FooterClient from './FooterClient';
|
||||
|
||||
export default async function Footer() {
|
||||
const session = await authCached();
|
||||
return (
|
||||
<FooterClient userEmail={session?.user?.email} />
|
||||
);
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import Link from 'next/link';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { isPathSignIn } from '@/site/paths';
|
||||
import { signOutAction } from '@/auth/action';
|
||||
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
|
||||
|
||||
const LINK_STYLE = clsx(
|
||||
'cursor-pointer',
|
||||
'hover:text-gray-300',
|
||||
'hover:dark:text-gray-600',
|
||||
);
|
||||
|
||||
export default function FooterAuth() {
|
||||
const { data: session, status } = useSession();
|
||||
|
||||
const path = usePathname();
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className={clsx(
|
||||
'flex items-center',
|
||||
'my-8',
|
||||
'text-dim',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-wrap items-center flex-grow">
|
||||
{status === 'loading'
|
||||
? <>Loading ...</>
|
||||
: <>
|
||||
{session?.user?.email && <div>
|
||||
{session.user.email}
|
||||
</div>}
|
||||
{status === 'authenticated' &&
|
||||
<form action={signOutAction}>
|
||||
<SubmitButtonWithStatus
|
||||
className={LINK_STYLE}
|
||||
styleAsLink
|
||||
>
|
||||
Sign Out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>}
|
||||
{status === 'unauthenticated' &&
|
||||
<Link
|
||||
href="/sign-in"
|
||||
className={LINK_STYLE}
|
||||
>
|
||||
Sign In
|
||||
</Link>}
|
||||
</>}
|
||||
</div>
|
||||
{!isPathSignIn(path) && <ThemeSwitcher />}
|
||||
</div>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
70
src/site/FooterClient.tsx
Normal file
70
src/site/FooterClient.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import Link from 'next/link';
|
||||
import { SHOW_REPO_LINK } from '@/site/config';
|
||||
import RepoLink from '../components/RepoLink';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { isPathAdmin, isPathSignIn, pathForAdminPhotos } from './paths';
|
||||
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
|
||||
import { signOutAction } from '@/auth/action';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
|
||||
export default function FooterClient({
|
||||
userEmail,
|
||||
}: {
|
||||
userEmail?: string | null | undefined
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
|
||||
const showFooter = !isPathSignIn(pathname);
|
||||
|
||||
const shouldAnimate = !isPathAdmin(pathname);
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={
|
||||
<AnimateItems
|
||||
type={!shouldAnimate ? 'none' : 'bottom'}
|
||||
distanceOffset={10}
|
||||
items={showFooter
|
||||
? [<div
|
||||
key="footer"
|
||||
className={clsx(
|
||||
'flex items-center',
|
||||
'text-dim min-h-[4rem]',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-grow flex-wrap h-4">
|
||||
{isPathAdmin(pathname)
|
||||
? <>
|
||||
{userEmail === undefined &&
|
||||
<Spinner />}
|
||||
{userEmail && <>
|
||||
<div>{userEmail}</div>
|
||||
<form action={signOutAction}>
|
||||
<SubmitButtonWithStatus styleAsLink>
|
||||
Sign out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>
|
||||
</>}
|
||||
</>
|
||||
: <>
|
||||
<Link href={pathForAdminPhotos()}>
|
||||
Admin
|
||||
</Link>
|
||||
{SHOW_REPO_LINK &&
|
||||
<RepoLink />}
|
||||
</>}
|
||||
</div>
|
||||
<div className="flex items-center h-4">
|
||||
<ThemeSwitcher />
|
||||
</div>
|
||||
</div>]
|
||||
: []}
|
||||
/>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import { signOut } from 'next-auth/react';
|
||||
import Link from 'next/link';
|
||||
import { SHOW_REPO_LINK } from '@/site/config';
|
||||
import RepoLink from '../components/RepoLink';
|
||||
|
||||
export default function FooterStatic({
|
||||
showSignOut,
|
||||
}: {
|
||||
showSignOut?: boolean
|
||||
}) {
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className={clsx(
|
||||
'my-8',
|
||||
'flex items-center',
|
||||
'text-dim',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-grow flex-wrap">
|
||||
<Link
|
||||
href="/admin/photos"
|
||||
className="hover:text-gray-600 dark:hover:text-gray-400"
|
||||
>
|
||||
Admin
|
||||
</Link>
|
||||
{SHOW_REPO_LINK &&
|
||||
<RepoLink />}
|
||||
{showSignOut &&
|
||||
<div
|
||||
className={clsx(
|
||||
'cursor-pointer',
|
||||
'hover:text-gray-600 dark:hover:text-gray-400',
|
||||
)}
|
||||
onClick={() => signOut()}
|
||||
>
|
||||
Sign out
|
||||
</div>}
|
||||
</div>
|
||||
<ThemeSwitcher />
|
||||
</div>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,82 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import { SITE_DOMAIN_OR_TITLE } from '@/site/config';
|
||||
import ViewSwitcher, { SwitcherSelection } from '@/site/ViewSwitcher';
|
||||
import {
|
||||
PATH_ADMIN,
|
||||
PATH_ROOT,
|
||||
isPathAdmin,
|
||||
isPathGrid,
|
||||
isPathProtected,
|
||||
isPathSets,
|
||||
isPathSignIn,
|
||||
} from '@/site/paths';
|
||||
import AnimateItems from '../components/AnimateItems';
|
||||
|
||||
export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) {
|
||||
const isLoggedIn = false;
|
||||
|
||||
const pathname = usePathname();
|
||||
|
||||
const showNav = !isPathSignIn(pathname);
|
||||
|
||||
const shouldAnimate = !isPathAdmin(pathname);
|
||||
|
||||
const renderLink = (
|
||||
text: string,
|
||||
linkOrAction: string | (() => void),
|
||||
) =>
|
||||
typeof linkOrAction === 'string'
|
||||
? <Link href={linkOrAction}>{text}</Link>
|
||||
: <button onClick={linkOrAction}>{text}</button>;
|
||||
|
||||
const switcherSelectionForPath = (): SwitcherSelection | undefined => {
|
||||
if (pathname === PATH_ROOT) {
|
||||
return 'full-frame';
|
||||
} else if (isPathGrid(pathname)) {
|
||||
return 'grid';
|
||||
} else if (isPathSets(pathname)) {
|
||||
return 'sets';
|
||||
} else if (isPathProtected(pathname)) {
|
||||
return 'admin';
|
||||
}
|
||||
};
|
||||
import { authCached } from '@/cache';
|
||||
import NavClient from './NavClient';
|
||||
|
||||
export default async function Nav() {
|
||||
const session = await authCached();
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={
|
||||
<AnimateItems
|
||||
type={!shouldAnimate ? 'none' : 'bottom'}
|
||||
distanceOffset={10}
|
||||
items={showNav
|
||||
? [<div
|
||||
key="nav"
|
||||
className={clsx(
|
||||
'flex items-center',
|
||||
'w-full min-h-[4rem]',
|
||||
'leading-none',
|
||||
)}>
|
||||
<div className="flex flex-grow items-center gap-4">
|
||||
<ViewSwitcher
|
||||
currentSelection={switcherSelectionForPath()}
|
||||
showAdmin={isLoggedIn}
|
||||
/>
|
||||
{showTextLinks && <>
|
||||
{renderLink('Home', PATH_ROOT)}
|
||||
{renderLink('Admin', PATH_ADMIN)}
|
||||
</>}
|
||||
</div>
|
||||
<div className="hidden xs:block">
|
||||
{renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
|
||||
</div>
|
||||
</div>]
|
||||
: []}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<NavClient showAdmin={Boolean(session?.user?.email)} />
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
79
src/site/NavClient.tsx
Normal file
79
src/site/NavClient.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import { SITE_DOMAIN_OR_TITLE } from '@/site/config';
|
||||
import ViewSwitcher, { SwitcherSelection } from '@/site/ViewSwitcher';
|
||||
import {
|
||||
PATH_ROOT,
|
||||
isPathAdmin,
|
||||
isPathGrid,
|
||||
isPathProtected,
|
||||
isPathSets,
|
||||
isPathSignIn,
|
||||
} from '@/site/paths';
|
||||
import AnimateItems from '../components/AnimateItems';
|
||||
|
||||
export default function NavClient({
|
||||
showAdmin,
|
||||
}: {
|
||||
showAdmin?: boolean,
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
|
||||
const showNav = !isPathSignIn(pathname);
|
||||
|
||||
const shouldAnimate = !isPathAdmin(pathname);
|
||||
|
||||
const renderLink = (
|
||||
text: string,
|
||||
linkOrAction: string | (() => void),
|
||||
) =>
|
||||
typeof linkOrAction === 'string'
|
||||
? <Link href={linkOrAction}>{text}</Link>
|
||||
: <button onClick={linkOrAction}>{text}</button>;
|
||||
|
||||
const switcherSelectionForPath = (): SwitcherSelection | undefined => {
|
||||
if (pathname === PATH_ROOT) {
|
||||
return 'full-frame';
|
||||
} else if (isPathGrid(pathname)) {
|
||||
return 'grid';
|
||||
} else if (isPathSets(pathname)) {
|
||||
return 'sets';
|
||||
} else if (isPathProtected(pathname)) {
|
||||
return 'admin';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={
|
||||
<AnimateItems
|
||||
type={!shouldAnimate ? 'none' : 'bottom'}
|
||||
distanceOffset={10}
|
||||
items={showNav
|
||||
? [<div
|
||||
key="nav"
|
||||
className={clsx(
|
||||
'flex items-center',
|
||||
'w-full min-h-[4rem]',
|
||||
'leading-none',
|
||||
)}>
|
||||
<div className="flex flex-grow items-center gap-4">
|
||||
<ViewSwitcher
|
||||
currentSelection={switcherSelectionForPath()}
|
||||
showAdmin={showAdmin}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden xs:block">
|
||||
{renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
|
||||
</div>
|
||||
</div>]
|
||||
: []}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -2,7 +2,7 @@ import Switcher from '@/components/Switcher';
|
||||
import SwitcherItem from '@/components/SwitcherItem';
|
||||
import IconFullFrame from '@/site/IconFullFrame';
|
||||
import IconGrid from '@/site/IconGrid';
|
||||
import { PATH_GRID, PATH_SETS } from '@/site/paths';
|
||||
import { PATH_ADMIN_PHOTOS, PATH_GRID, PATH_SETS } from '@/site/paths';
|
||||
import { BiLockAlt } from 'react-icons/bi';
|
||||
import IconSets from './IconSets';
|
||||
|
||||
@ -38,8 +38,8 @@ export default function ViewSwitcher({
|
||||
/>
|
||||
{showAdmin &&
|
||||
<SwitcherItem
|
||||
icon={<BiLockAlt size={15} className="-translate-y-[1px]" />}
|
||||
href="/admin/photos"
|
||||
icon={<BiLockAlt size={16} className="translate-y-[-0.5px]" />}
|
||||
href={PATH_ADMIN_PHOTOS}
|
||||
active={currentSelection === 'admin'}
|
||||
/>}
|
||||
</Switcher>
|
||||
|
||||
@ -107,6 +107,11 @@
|
||||
p-0 min-h-0
|
||||
border-none active:bg-transparent shadow-none
|
||||
}
|
||||
a, .link {
|
||||
@apply
|
||||
hover:text-gray-600
|
||||
hover:dark:text-gray-400
|
||||
}
|
||||
/* Common Utilities */
|
||||
.text-main {
|
||||
@apply
|
||||
|
||||
Loading…
Reference in New Issue
Block a user