Inital commit
This commit is contained in:
commit
5f12ccfa34
32 changed files with 2708 additions and 0 deletions
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
node_modules
|
||||
|
||||
# Output
|
||||
.output
|
||||
.vercel
|
||||
.netlify
|
||||
.wrangler
|
||||
/.svelte-kit
|
||||
/build
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.test
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
1
.npmrc
Normal file
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
|||
engine-strict=true
|
38
README.md
Normal file
38
README.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# sv
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
services:
|
||||
caddy:
|
||||
image: caddy:latest
|
||||
volumes:
|
||||
- "./docker/Caddyfile:/etc/caddy/Caddyfile"
|
||||
ports:
|
||||
- "8080:8080"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
pocketbase:
|
||||
image: ghcr.io/muchobien/pocketbase:latest
|
||||
ports:
|
||||
- "8090:8090"
|
||||
healthcheck: # optional, recommended since v0.10.0
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:8090/api/health || exit 1
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
25
docker/Caddyfile
Normal file
25
docker/Caddyfile
Normal file
|
@ -0,0 +1,25 @@
|
|||
# The Caddyfile is an easy way to configure your Caddy web server.
|
||||
#
|
||||
# Unless the file starts with a global options block, the first
|
||||
# uncommented line is always the address of your site.
|
||||
#
|
||||
# To use your own domain name (with automatic HTTPS), first make
|
||||
# sure your domain's A/AAAA DNS records are properly pointed to
|
||||
# this machine's public IP, then replace ":80" below with your
|
||||
# domain name.
|
||||
|
||||
http://fedora.raccoon-nase.ts.net:8080 {
|
||||
# Set this path to your site's directory.
|
||||
root * /usr/share/caddy
|
||||
|
||||
# Another common task is to set up a reverse proxy:
|
||||
reverse_proxy http://host.docker.internal:5173
|
||||
reverse_proxy /api/* http://pocketbase:8090
|
||||
reverse_proxy /_/* http://pocketbase:8090
|
||||
|
||||
# Or serve a PHP site through php-fpm:
|
||||
# php_fastcgi localhost:9000
|
||||
}
|
||||
|
||||
# Refer to the Caddy docs for more information:
|
||||
# https://caddyserver.com/docs/caddyfile
|
988
docker/pocketbase/pb_schema.json
Normal file
988
docker/pocketbase/pb_schema.json
Normal file
|
@ -0,0 +1,988 @@
|
|||
[
|
||||
{
|
||||
"id": "pbc_3142635823",
|
||||
"listRule": null,
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "_superusers",
|
||||
"type": "auth",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cost": 0,
|
||||
"hidden": true,
|
||||
"id": "password901924565",
|
||||
"max": 0,
|
||||
"min": 8,
|
||||
"name": "password",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "[a-zA-Z0-9]{50}",
|
||||
"hidden": true,
|
||||
"id": "text2504183744",
|
||||
"max": 60,
|
||||
"min": 30,
|
||||
"name": "tokenKey",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "email3885137012",
|
||||
"name": "email",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool1547992806",
|
||||
"name": "emailVisibility",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool256245529",
|
||||
"name": "verified",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX `idx_tokenKey_pbc_3142635823` ON `_superusers` (`tokenKey`)",
|
||||
"CREATE UNIQUE INDEX `idx_email_pbc_3142635823` ON `_superusers` (`email`) WHERE `email` != ''"
|
||||
],
|
||||
"system": true,
|
||||
"authRule": "",
|
||||
"manageRule": null,
|
||||
"authAlert": {
|
||||
"enabled": true,
|
||||
"emailTemplate": {
|
||||
"subject": "Login from a new location",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"oauth2": {
|
||||
"mappedFields": {
|
||||
"id": "",
|
||||
"name": "",
|
||||
"username": "",
|
||||
"avatarURL": ""
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"passwordAuth": {
|
||||
"enabled": true,
|
||||
"identityFields": [
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"mfa": {
|
||||
"enabled": false,
|
||||
"duration": 1800,
|
||||
"rule": ""
|
||||
},
|
||||
"otp": {
|
||||
"enabled": false,
|
||||
"duration": 180,
|
||||
"length": 8,
|
||||
"emailTemplate": {
|
||||
"subject": "OTP for {APP_NAME}",
|
||||
"body": "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"authToken": {
|
||||
"duration": 86400
|
||||
},
|
||||
"passwordResetToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"emailChangeToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"verificationToken": {
|
||||
"duration": 259200
|
||||
},
|
||||
"fileToken": {
|
||||
"duration": 180
|
||||
},
|
||||
"verificationTemplate": {
|
||||
"subject": "Verify your {APP_NAME} email",
|
||||
"body": "<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Verify</a>\n</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"resetPasswordTemplate": {
|
||||
"subject": "Reset your {APP_NAME} password",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Reset password</a>\n</p>\n<p><i>If you didn't ask to reset your password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"confirmEmailChangeTemplate": {
|
||||
"subject": "Confirm your {APP_NAME} new email address",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Confirm new email</a>\n</p>\n<p><i>If you didn't ask to change your email address, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "_pb_users_auth_",
|
||||
"listRule": "id = @request.auth.id",
|
||||
"viewRule": "id = @request.auth.id",
|
||||
"createRule": "",
|
||||
"updateRule": "id = @request.auth.id",
|
||||
"deleteRule": "id = @request.auth.id",
|
||||
"name": "users",
|
||||
"type": "auth",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cost": 0,
|
||||
"hidden": true,
|
||||
"id": "password901924565",
|
||||
"max": 0,
|
||||
"min": 8,
|
||||
"name": "password",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "[a-zA-Z0-9]{50}",
|
||||
"hidden": true,
|
||||
"id": "text2504183744",
|
||||
"max": 60,
|
||||
"min": 30,
|
||||
"name": "tokenKey",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"exceptDomains": null,
|
||||
"hidden": false,
|
||||
"id": "email3885137012",
|
||||
"name": "email",
|
||||
"onlyDomains": null,
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "email"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool1547992806",
|
||||
"name": "emailVisibility",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "bool256245529",
|
||||
"name": "verified",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 255,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "file376926767",
|
||||
"maxSelect": 1,
|
||||
"maxSize": 0,
|
||||
"mimeTypes": [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/gif",
|
||||
"image/webp"
|
||||
],
|
||||
"name": "avatar",
|
||||
"presentable": false,
|
||||
"protected": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"thumbs": null,
|
||||
"type": "file"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
|
||||
"CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
|
||||
],
|
||||
"system": false,
|
||||
"authRule": "",
|
||||
"manageRule": null,
|
||||
"authAlert": {
|
||||
"enabled": true,
|
||||
"emailTemplate": {
|
||||
"subject": "Login from a new location",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"oauth2": {
|
||||
"mappedFields": {
|
||||
"id": "",
|
||||
"name": "name",
|
||||
"username": "",
|
||||
"avatarURL": "avatar"
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"passwordAuth": {
|
||||
"enabled": true,
|
||||
"identityFields": [
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"mfa": {
|
||||
"enabled": false,
|
||||
"duration": 1800,
|
||||
"rule": ""
|
||||
},
|
||||
"otp": {
|
||||
"enabled": false,
|
||||
"duration": 180,
|
||||
"length": 8,
|
||||
"emailTemplate": {
|
||||
"subject": "OTP for {APP_NAME}",
|
||||
"body": "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
"authToken": {
|
||||
"duration": 604800
|
||||
},
|
||||
"passwordResetToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"emailChangeToken": {
|
||||
"duration": 1800
|
||||
},
|
||||
"verificationToken": {
|
||||
"duration": 259200
|
||||
},
|
||||
"fileToken": {
|
||||
"duration": 180
|
||||
},
|
||||
"verificationTemplate": {
|
||||
"subject": "Verify your {APP_NAME} email",
|
||||
"body": "<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Verify</a>\n</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"resetPasswordTemplate": {
|
||||
"subject": "Reset your {APP_NAME} password",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Reset password</a>\n</p>\n<p><i>If you didn't ask to reset your password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
},
|
||||
"confirmEmailChangeTemplate": {
|
||||
"subject": "Confirm your {APP_NAME} new email address",
|
||||
"body": "<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Confirm new email</a>\n</p>\n<p><i>If you didn't ask to change your email address, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "pbc_4275539003",
|
||||
"listRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"viewRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"name": "_authOrigins",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text455797646",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "collectionRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text127846527",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "recordRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text4228609354",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "fingerprint",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX `idx_authOrigins_unique_pairs` ON `_authOrigins` (collectionRef, recordRef, fingerprint)"
|
||||
],
|
||||
"system": true
|
||||
},
|
||||
{
|
||||
"id": "pbc_2281828961",
|
||||
"listRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"viewRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"name": "_externalAuths",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text455797646",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "collectionRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text127846527",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "recordRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2462348188",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "provider",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1044722854",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "providerId",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX `idx_externalAuths_record_provider` ON `_externalAuths` (collectionRef, recordRef, provider)",
|
||||
"CREATE UNIQUE INDEX `idx_externalAuths_collection_provider` ON `_externalAuths` (collectionRef, provider, providerId)"
|
||||
],
|
||||
"system": true
|
||||
},
|
||||
{
|
||||
"id": "pbc_2279338944",
|
||||
"listRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"viewRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "_mfas",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text455797646",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "collectionRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text127846527",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "recordRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1582905952",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "method",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE INDEX `idx_mfas_collectionRef_recordRef` ON `_mfas` (collectionRef,recordRef)"
|
||||
],
|
||||
"system": true
|
||||
},
|
||||
{
|
||||
"id": "pbc_1638494021",
|
||||
"listRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"viewRule": "@request.auth.id != '' && recordRef = @request.auth.id && collectionRef = @request.auth.collectionId",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "_otps",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text455797646",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "collectionRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text127846527",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "recordRef",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cost": 8,
|
||||
"hidden": true,
|
||||
"id": "password901924565",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "password",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "password"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": true,
|
||||
"id": "text3866985172",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "sentTo",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": true,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE INDEX `idx_otps_collectionRef_recordRef` ON `_otps` (collectionRef, recordRef)"
|
||||
],
|
||||
"system": true
|
||||
},
|
||||
{
|
||||
"id": "pbc_1687431684",
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "events",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text724990059",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "title",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"convertURLs": false,
|
||||
"hidden": false,
|
||||
"id": "editor1843675174",
|
||||
"maxSize": 0,
|
||||
"name": "description",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "editor"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2560465762",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "slug",
|
||||
"pattern": "^[a-zA-Z0-9\\-]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": true,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "pbc_1942858786",
|
||||
"hidden": false,
|
||||
"id": "relation1587448267",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "location",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"system": false
|
||||
},
|
||||
{
|
||||
"id": "pbc_1942858786",
|
||||
"listRule": null,
|
||||
"viewRule": "",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "locations",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 15,
|
||||
"min": 15,
|
||||
"name": "id",
|
||||
"pattern": "^[a-z0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text223244161",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "address",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number2499937429",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "lat",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number2518964612",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "lng",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number3073079668",
|
||||
"max": 20,
|
||||
"min": 1,
|
||||
"name": "zoom",
|
||||
"onlyInt": true,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate2990389176",
|
||||
"name": "created",
|
||||
"onCreate": true,
|
||||
"onUpdate": false,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "autodate3332085495",
|
||||
"name": "updated",
|
||||
"onCreate": true,
|
||||
"onUpdate": true,
|
||||
"presentable": false,
|
||||
"system": false,
|
||||
"type": "autodate"
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"system": false
|
||||
}
|
||||
]
|
19
jsconfig.json
Normal file
19
jsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler"
|
||||
}
|
||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
29
package.json
Normal file
29
package.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "cologne-furmeet-reg",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite dev --host 0.0.0.0",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^4.0.0",
|
||||
"@sveltejs/kit": "^2.16.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jdenticon": "^3.3.0",
|
||||
"ol": "^10.4.0",
|
||||
"pocketbase": "^0.25.1"
|
||||
}
|
||||
}
|
1113
pnpm-lock.yaml
Normal file
1113
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
60
src/app.css
Normal file
60
src/app.css
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* inter-regular - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('/fonts/inter-v18-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
|
||||
* {
|
||||
--color-primary-a0: #ffffff;
|
||||
--color-primary-a10: #e1e6fe;
|
||||
--color-primary-a20: #c2cdfd;
|
||||
--color-primary-a30: #a1b5fb;
|
||||
--color-primary-a40: #7d9df9;
|
||||
--color-primary-a50: #5087f6;
|
||||
--color-primary-a60: #436bc0;
|
||||
--color-primary-a70: #364f8c;
|
||||
--color-primary-a80: #28365c;
|
||||
--color-primary-a90: #191e2f;
|
||||
--color-primary-a100: #000000;
|
||||
--text-color: black;
|
||||
|
||||
box-sizing: border-box;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: white;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p, a, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: Inter, Arial, sans-serif;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.35rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
svg {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
13
src/app.d.ts
vendored
Normal file
13
src/app.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
13
src/app.html
Normal file
13
src/app.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script src="https://telegram.org/js/telegram-web-app.js?56"></script>
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
5
src/hooks.client.js
Normal file
5
src/hooks.client.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import {initializePocketBase} from "$lib/pocketbase.js";
|
||||
|
||||
export const init = async () => {
|
||||
initializePocketBase()
|
||||
}
|
5
src/hooks.server.js
Normal file
5
src/hooks.server.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import {initializePocketBase} from "$lib/pocketbase.js";
|
||||
|
||||
export const init = async () => {
|
||||
initializePocketBase()
|
||||
}
|
36
src/lib/components/ContainerGridSingle.svelte
Normal file
36
src/lib/components/ContainerGridSingle.svelte
Normal file
|
@ -0,0 +1,36 @@
|
|||
<script>
|
||||
const {children, footer} = $props();
|
||||
</script>
|
||||
|
||||
<div class="container-grid">
|
||||
<main>
|
||||
{@render children()}
|
||||
</main>
|
||||
<footer>
|
||||
{@render footer()}
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container-grid {
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
grid-template-columns: [content-full-start] 2rem [content-start] 1fr [content-end] 2rem [content-full-end];
|
||||
grid-template-rows: [content-header] 1fr [content-footer-start] min-content [content-footer-end];
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 1rem;
|
||||
grid-column: content;
|
||||
}
|
||||
|
||||
footer {
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
position: sticky;
|
||||
grid-column: content;
|
||||
grid-row: content-footer;
|
||||
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
13
src/lib/components/ContentGrid.svelte
Normal file
13
src/lib/components/ContentGrid.svelte
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script>
|
||||
const {children} = $props();
|
||||
</script>
|
||||
|
||||
<div class="content-grid">
|
||||
{@render children()}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.content-grid {
|
||||
grid-column: content;
|
||||
}
|
||||
</style>
|
27
src/lib/components/EventList.svelte
Normal file
27
src/lib/components/EventList.svelte
Normal file
|
@ -0,0 +1,27 @@
|
|||
<script>
|
||||
const {events} = $props();
|
||||
|
||||
</script>
|
||||
|
||||
<div class="event-list">
|
||||
{#if events}
|
||||
{#each events as event}
|
||||
<div class="event">
|
||||
<h2>{event?.title ?? "No title"}</h2>
|
||||
<p class="event-description">{@html event?.description}</p>
|
||||
<p><a href={"/events/" + event.slug}>Details</a></p>
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
<p>No events</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.event {
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
border: 2px solid #00000055;
|
||||
border-radius: 3%;
|
||||
}
|
||||
</style>
|
43
src/lib/components/FooterNavigation.svelte
Normal file
43
src/lib/components/FooterNavigation.svelte
Normal file
|
@ -0,0 +1,43 @@
|
|||
<script>
|
||||
import { page } from '$app/state';
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li class:selected={page.url.pathname === "/"}>
|
||||
<a href="/" >Start</a>
|
||||
</li>
|
||||
<li class:selected={page.url.pathname === "/events"}>
|
||||
<a href="/events">Events</a>
|
||||
</li>
|
||||
<li class:selected={page.url.pathname === "/rules"}>
|
||||
<a href="/rules">Regeln</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li {
|
||||
transition: border-bottom-color linear 0.2s;
|
||||
padding: 0.6rem 0.45rem;
|
||||
border-bottom: 3px var(--color-primary-a80) solid;
|
||||
|
||||
&.selected {
|
||||
border-bottom: 3px var(--color-primary-a40) solid;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
32
src/lib/components/RoundedAvatar.svelte
Normal file
32
src/lib/components/RoundedAvatar.svelte
Normal file
|
@ -0,0 +1,32 @@
|
|||
<script>
|
||||
const {src, alt = "Profile image"} = $props();
|
||||
import jdenticon from "jdenticon/standalone";
|
||||
</script>
|
||||
|
||||
<div class="rounded-avatar-wrapper">
|
||||
{#if src}
|
||||
<img class="rounded-avatar" {src} {alt} />
|
||||
{:else}
|
||||
{@const randomAvatar = jdenticon.toSvg(Navigator.userAgent, 320, { padding: 0 })}
|
||||
<div class="rounded-avatar">
|
||||
{@html randomAvatar}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.rounded-avatar-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rounded-avatar {
|
||||
overflow: hidden;
|
||||
border-radius: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
1
src/lib/index.js
Normal file
1
src/lib/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
13
src/lib/pocketbase.js
Normal file
13
src/lib/pocketbase.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import PocketBase from 'pocketbase';
|
||||
import {PUBLIC_POCKETBASE_URL} from "$env/static/public";
|
||||
|
||||
let pocketbase;
|
||||
|
||||
export function initializePocketBase() {
|
||||
pocketbase = new PocketBase(PUBLIC_POCKETBASE_URL);
|
||||
return pocketbase;
|
||||
}
|
||||
|
||||
export function usePocketBase() {
|
||||
return pocketbase;
|
||||
}
|
27
src/routes/+layout.svelte
Normal file
27
src/routes/+layout.svelte
Normal file
|
@ -0,0 +1,27 @@
|
|||
<script>
|
||||
import '../app.css';
|
||||
import FooterNavigation from "$lib/components/FooterNavigation.svelte";
|
||||
import ContainerGridSingle from "$lib/components/ContainerGridSingle.svelte";
|
||||
const { children } = $props();
|
||||
|
||||
$effect(() => {
|
||||
Telegram?.WebApp?.ready();
|
||||
Telegram?.WebApp?.setBackgroundColor('FFFFFF');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<ContainerGridSingle>
|
||||
{@render children()}
|
||||
{#snippet footer()}
|
||||
<div class="footer-inner">
|
||||
<FooterNavigation></FooterNavigation>
|
||||
</div>
|
||||
{/snippet}
|
||||
</ContainerGridSingle>
|
||||
|
||||
<style>
|
||||
.footer-inner {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
25
src/routes/+page.svelte
Normal file
25
src/routes/+page.svelte
Normal file
|
@ -0,0 +1,25 @@
|
|||
<script>
|
||||
import RoundedAvatar from "$lib/components/RoundedAvatar.svelte";
|
||||
let user = $state(null);
|
||||
|
||||
$effect(() => {
|
||||
const searchParams = new URLSearchParams(Telegram?.WebApp?.initData);
|
||||
const tempUser = searchParams.get('user');
|
||||
if (!tempUser) {
|
||||
console.warn("User could not be loaded");
|
||||
return;
|
||||
}
|
||||
user = JSON.parse(tempUser);
|
||||
})
|
||||
</script>
|
||||
|
||||
<section id="intro">
|
||||
{#if user}
|
||||
<RoundedAvatar src={user?.photo_url}></RoundedAvatar>
|
||||
<h2>Hallo {user.first_name}!</h2>
|
||||
{:else}
|
||||
<RoundedAvatar src={null}></RoundedAvatar>
|
||||
<h2>Hallo Besucher!</h2>
|
||||
{/if}
|
||||
<p>Du befinest dich auf der Anmeldeseite des Kölner Stammtischs. Schau dir die unteren Menüpunkte an, falls du mehr erfahren möchtest.</p>
|
||||
</section>
|
10
src/routes/events/+page.js
Normal file
10
src/routes/events/+page.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import PocketBase from "pocketbase";
|
||||
import {PUBLIC_POCKETBASE_URL} from "$env/static/public";
|
||||
|
||||
export const load = async ({ fetch }) => {
|
||||
const pb = new PocketBase(PUBLIC_POCKETBASE_URL);
|
||||
|
||||
return {
|
||||
eventCollection: await pb.collection("events").getFullList({fetch})
|
||||
};
|
||||
}
|
8
src/routes/events/+page.svelte
Normal file
8
src/routes/events/+page.svelte
Normal file
|
@ -0,0 +1,8 @@
|
|||
<script>
|
||||
import EventList from "$lib/components/EventList.svelte";
|
||||
const {data} = $props();
|
||||
const {eventCollection} = data;
|
||||
</script>
|
||||
|
||||
<h1>Events</h1>
|
||||
<EventList events={eventCollection}></EventList>
|
19
src/routes/events/[slug]/+page.js
Normal file
19
src/routes/events/[slug]/+page.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import PocketBase from "pocketbase";
|
||||
import { PUBLIC_POCKETBASE_URL } from "$env/static/public";
|
||||
import { error } from '@sveltejs/kit'
|
||||
|
||||
export const load = async ({ params, fetch }) => {
|
||||
const pb = new PocketBase(PUBLIC_POCKETBASE_URL);
|
||||
let event = null;
|
||||
try {
|
||||
event = await pb.collection("events").getFirstListItem("slug = '" + params.slug + "'", {fetch, expand: "location"});
|
||||
} catch (e) {
|
||||
throw error(404, {
|
||||
message: "Not found"
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
event
|
||||
};
|
||||
}
|
71
src/routes/events/[slug]/+page.svelte
Normal file
71
src/routes/events/[slug]/+page.svelte
Normal file
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
import '../../../../node_modules/ol/ol.css';
|
||||
import {Map, View} from 'ol';
|
||||
import {OSM} from 'ol/source';
|
||||
import {Tile} from 'ol/layer';
|
||||
import {useGeographic} from "ol/proj";
|
||||
import {onMount} from "svelte";
|
||||
|
||||
const { data } = $props();
|
||||
const { event } = data;
|
||||
|
||||
let mapRef;
|
||||
|
||||
onMount(() => {
|
||||
let lat = event?.expand?.location?.lat ?? null,
|
||||
lng = event?.expand?.location?.lng ?? null;
|
||||
|
||||
if (lat && lng) {
|
||||
const zoom = event?.expand?.location?.zoom ?? 18;
|
||||
console.log(lat, lng)
|
||||
useGeographic();
|
||||
new Map({
|
||||
target: mapRef,
|
||||
layers: [
|
||||
new Tile({
|
||||
source: new OSM()
|
||||
})
|
||||
],
|
||||
view: new View({
|
||||
center: [lng, lat],
|
||||
zoom,
|
||||
}),
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="event-detail">
|
||||
<h1>{event?.title ?? "No title"}</h1>
|
||||
{#if event?.description}
|
||||
{@html event.description}
|
||||
{:else}
|
||||
<p>{event?.description ?? "No description"}</p>
|
||||
{/if}
|
||||
|
||||
<div class="event-location-details">
|
||||
<h2>Location</h2>
|
||||
<p class="location-address">
|
||||
{event?.expand?.location?.name}<br />
|
||||
{event?.expand?.location?.address}
|
||||
</p>
|
||||
<div class="event-map" bind:this={mapRef}></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.event-map {
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
.event-location-details {
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
border: 2px solid #00000055;
|
||||
border-radius: 3%;
|
||||
}
|
||||
|
||||
.location-address {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
11
src/routes/rules/+page.svelte
Normal file
11
src/routes/rules/+page.svelte
Normal file
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
</script>
|
||||
|
||||
<iframe src="https://www.furries.cologne/stammi-regeln/"></iframe>
|
||||
|
||||
<style>
|
||||
iframe {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
static/fonts/inter-v18-latin-regular.woff2
Normal file
BIN
static/fonts/inter-v18-latin-regular.woff2
Normal file
Binary file not shown.
13
svelte.config.js
Normal file
13
svelte.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import adapter from '@sveltejs/adapter-auto';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
9
vite.config.js
Normal file
9
vite.config.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
server: {
|
||||
allowedHosts: ['fedora.raccoon-nase.ts.net']
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue