diff --git a/README.md b/README.md
index 04e2524..2e5005c 100644
--- a/README.md
+++ b/README.md
@@ -13,11 +13,21 @@
> Relax, have a satsuma and enjoy the next trip to the supermarket.
>
-
That's at least the vision for this little helper app.
Try it out live 👉 [here](https://main--satsuma-shopping.netlify.app) 👈
+## Roadmap
+
+- [ ] Add Sharing-feature
+- [ ] Add email-service for password reset and email verification
+- [ ] Protect signup and signin with ReCaptcha
+- [ ] Add GoatCounter analytics
+- [ ] Improve DevOps and hosting
+- [ ] Launch Party 🚀
+
+After that, we'll focus on improvements, new ideas and possibly explore a paid-plan. We welcome your suggestions.
+
## Setup
1. Run `nvm use` in the project root to ensure the right node version is used.
@@ -34,3 +44,4 @@ The pocketbase executable should be run in a separate folder.
- 🎨 [Color Scheme](https://coolors.co/cdf0ea-f9f9f9-f7dbf0-beaee2-513956)
- 🛢️ [Host PB for free on Fly.io](https://github.com/pocketbase/pocketbase/discussions/537)
- 📱 [Icons](https://icones.js.org/)
+
diff --git a/backend/fly.toml b/backend/fly.toml
index efe2482..36800eb 100644
--- a/backend/fly.toml
+++ b/backend/fly.toml
@@ -1,45 +1,41 @@
-# fly.toml file generated for satsuma on 2023-03-31T08:51:17+02:00
+# fly.toml app configuration file generated for satsuma on 2023-08-21T08:44:04+02:00
+#
+# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
+#
app = "satsuma"
+primary_region = "arn"
kill_signal = "SIGINT"
-kill_timeout = 5
-processes = []
-
-[env]
+kill_timeout = "5s"
[experimental]
auto_rollback = true
-[mounts]
- destination = "/pb/pb_data"
+[[mounts]]
source = "pb_data"
-
-# optional if you want to change the PocketBase version
-[build.args]
- PB_VERSION="0.16.0"
+ destination = "/pb/pb_data"
+ processes = ["app"]
[[services]]
- http_checks = []
+ protocol = "tcp"
internal_port = 8080
processes = ["app"]
- protocol = "tcp"
- script_checks = []
- [services.concurrency]
- hard_limit = 25
- soft_limit = 20
- type = "connections"
[[services.ports]]
- force_https = true
- handlers = ["http"]
port = 80
+ handlers = ["http"]
+ force_https = true
[[services.ports]]
- handlers = ["tls", "http"]
port = 443
+ handlers = ["tls", "http"]
+ [services.concurrency]
+ type = "connections"
+ hard_limit = 25
+ soft_limit = 20
[[services.tcp_checks]]
- grace_period = "1s"
interval = "15s"
- restart_limit = 0
timeout = "2s"
+ grace_period = "1s"
+ restart_limit = 0
diff --git a/backend/pb_schema.json b/backend/pb_schema.json
index dee1388..f1e61c5 100644
--- a/backend/pb_schema.json
+++ b/backend/pb_schema.json
@@ -1,100 +1,86 @@
[
{
- "id": "_pb_users_auth_",
- "name": "users",
- "type": "auth",
+ "id": "945dqudy3xbgwei",
+ "name": "items",
+ "type": "base",
"system": false,
"schema": [
{
- "id": "users_name",
+ "id": "wosysey5",
"name": "name",
"type": "text",
"system": false,
- "required": false,
+ "required": true,
"options": {
"min": null,
"max": null,
"pattern": ""
}
- }
- ],
- "indexes": [],
- "listRule": "id = @request.auth.id",
- "viewRule": "id = @request.auth.id",
- "createRule": "",
- "updateRule": "id = @request.auth.id",
- "deleteRule": "id = @request.auth.id",
- "options": {
- "allowEmailAuth": false,
- "allowOAuth2Auth": false,
- "allowUsernameAuth": true,
- "exceptEmailDomains": null,
- "manageRule": null,
- "minPasswordLength": 8,
- "onlyEmailDomains": null,
- "requireEmail": false
- }
- },
- {
- "id": "pcgfoipcvldtrjb",
- "name": "categories",
- "type": "base",
- "system": false,
- "schema": [
+ },
{
- "id": "ytn1hobj",
- "name": "name",
- "type": "text",
+ "id": "pxvwelcb",
+ "name": "quantity",
+ "type": "number",
"system": false,
"required": true,
"options": {
"min": null,
- "max": null,
- "pattern": ""
+ "max": null
}
},
{
- "id": "ckwtmrxr",
- "name": "order",
- "type": "number",
+ "id": "1o8z4fwo",
+ "name": "category",
+ "type": "relation",
"system": false,
"required": false,
"options": {
- "min": null,
- "max": null
+ "collectionId": "pcgfoipcvldtrjb",
+ "cascadeDelete": false,
+ "minSelect": null,
+ "maxSelect": 1,
+ "displayFields": []
}
},
{
- "id": "lvscdvnh",
- "name": "user",
+ "id": "wioktqu4",
+ "name": "list",
"type": "relation",
"system": false,
"required": true,
"options": {
- "collectionId": "_pb_users_auth_",
+ "collectionId": "7hl5j2inxaqx1by",
"cascadeDelete": false,
"minSelect": null,
"maxSelect": 1,
"displayFields": []
}
+ },
+ {
+ "id": "hp9nitep",
+ "name": "picked",
+ "type": "bool",
+ "system": false,
+ "required": false,
+ "options": {}
}
],
"indexes": [],
- "listRule": "@request.auth.id = user",
- "viewRule": "@request.auth.id = user",
- "createRule": "@request.auth.id = user",
- "updateRule": "@request.auth.id = user",
- "deleteRule": "@request.auth.id = user",
+ "listRule": "",
+ "viewRule": "",
+ "createRule": "",
+ "updateRule": "",
+ "deleteRule": "",
"options": {}
},
{
- "id": "945dqudy3xbgwei",
- "name": "items",
+ "id": "7hl5j2inxaqx1by",
+ "name": "lists",
"type": "base",
"system": false,
"schema": [
{
- "id": "wosysey5",
+ "id": "8maejv7f",
"name": "name",
"type": "text",
"system": false,
@@ -106,24 +92,87 @@
}
},
{
- "id": "pxvwelcb",
- "name": "quantity",
- "type": "number",
+ "id": "rqjs1ran",
+ "name": "isTemplate",
+ "type": "bool",
+ "system": false,
+ "required": false,
+ "options": {}
+ },
+ {
+ "id": "icnarmhj",
+ "name": "owner",
+ "type": "relation",
"system": false,
"required": true,
"options": {
- "min": null,
- "max": null
+ "collectionId": "_pb_users_auth_",
+ "cascadeDelete": false,
+ "minSelect": null,
+ "maxSelect": 1,
+ "displayFields": []
}
},
{
- "id": "1o8z4fwo",
- "name": "category",
+ "id": "idfzoynb",
+ "name": "sharedWith",
"type": "relation",
"system": false,
"required": false,
"options": {
- "collectionId": "pcgfoipcvldtrjb",
+ "collectionId": "_pb_users_auth_",
+ "cascadeDelete": false,
+ "minSelect": null,
+ "maxSelect": null,
+ "displayFields": []
+ }
+ }
+ ],
+ "indexes": [],
+ "listRule": "@request.auth.id = owner || @request.auth.id ?= sharedWith.id",
+ "viewRule": "@request.auth.id = owner || @request.auth.id ?= sharedWith.id",
+ "createRule": "@request.auth.id = owner",
+ "updateRule": "@request.auth.id = owner",
+ "deleteRule": "@request.auth.id = owner",
+ "options": {}
+ },
+ {
+ "id": "_pb_users_auth_",
+ "name": "users",
+ "type": "auth",
+ "system": false,
+ "schema": [],
+ "indexes": [],
+ "listRule": "",
+ "viewRule": "",
+ "createRule": "",
+ "updateRule": "id = @request.auth.id",
+ "deleteRule": "id = @request.auth.id",
+ "options": {
+ "allowEmailAuth": true,
+ "allowOAuth2Auth": false,
+ "allowUsernameAuth": true,
+ "exceptEmailDomains": null,
+ "manageRule": null,
+ "minPasswordLength": 8,
+ "onlyEmailDomains": null,
+ "requireEmail": true
+ }
+ },
+ {
+ "id": "2jwei9mpvwduqyj",
+ "name": "invitations",
+ "type": "base",
+ "system": false,
+ "schema": [
+ {
+ "id": "xwzxywuu",
+ "name": "owner",
+ "type": "relation",
+ "system": false,
+ "required": false,
+ "options": {
+ "collectionId": "_pb_users_auth_",
"cascadeDelete": false,
"minSelect": null,
"maxSelect": 1,
@@ -131,11 +180,11 @@
}
},
{
- "id": "garp0pqf",
- "name": "user",
+ "id": "01se4eh7",
+ "name": "guest",
"type": "relation",
"system": false,
- "required": true,
+ "required": false,
"options": {
"collectionId": "_pb_users_auth_",
"cascadeDelete": false,
@@ -145,11 +194,11 @@
}
},
{
- "id": "wioktqu4",
+ "id": "plw0rv47",
"name": "list",
"type": "relation",
"system": false,
- "required": true,
+ "required": false,
"options": {
"collectionId": "7hl5j2inxaqx1by",
"cascadeDelete": false,
@@ -159,30 +208,49 @@
}
},
{
- "id": "hp9nitep",
- "name": "picked",
- "type": "bool",
+ "id": "hoyaw1qe",
+ "name": "state",
+ "type": "select",
"system": false,
"required": false,
- "options": {}
+ "options": {
+ "maxSelect": 1,
+ "values": [
+ "Pending",
+ "Accepted",
+ "Declined"
+ ]
+ }
+ },
+ {
+ "id": "fp4wauvn",
+ "name": "ownerName",
+ "type": "text",
+ "system": false,
+ "required": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
}
],
"indexes": [],
- "listRule": "@request.auth.id = user",
- "viewRule": "@request.auth.id = user",
- "createRule": "@request.auth.id = user",
- "updateRule": "@request.auth.id = user",
- "deleteRule": "@request.auth.id = user",
+ "listRule": "@request.auth.id = owner || @request.auth.id = guest",
+ "viewRule": "@request.auth.id = owner || @request.auth.id = guest",
+ "createRule": "@request.auth.id = owner",
+ "updateRule": "@request.auth.id = owner || @request.auth.id = guest",
+ "deleteRule": "@request.auth.id = owner ",
"options": {}
},
{
- "id": "7hl5j2inxaqx1by",
- "name": "lists",
+ "id": "pcgfoipcvldtrjb",
+ "name": "categories",
"type": "base",
"system": false,
"schema": [
{
- "id": "8maejv7f",
+ "id": "ytn1hobj",
"name": "name",
"type": "text",
"system": false,
@@ -194,16 +262,19 @@
}
},
{
- "id": "rqjs1ran",
- "name": "isTemplate",
- "type": "bool",
+ "id": "ckwtmrxr",
+ "name": "order",
+ "type": "number",
"system": false,
"required": false,
- "options": {}
+ "options": {
+ "min": null,
+ "max": null
+ }
},
{
- "id": "icnarmhj",
- "name": "user",
+ "id": "lvscdvnh",
+ "name": "owner",
"type": "relation",
"system": false,
"required": true,
@@ -217,11 +288,11 @@
}
],
"indexes": [],
- "listRule": "@request.auth.id = user",
- "viewRule": "@request.auth.id = user",
- "createRule": "@request.auth.id = user",
- "updateRule": "@request.auth.id = user",
- "deleteRule": "@request.auth.id = user",
+ "listRule": "",
+ "viewRule": "",
+ "createRule": "@request.auth.id = owner",
+ "updateRule": "@request.auth.id = owner",
+ "deleteRule": "@request.auth.id = owner",
"options": {}
}
]
\ No newline at end of file
diff --git a/src/lib/components/Divider.svelte b/src/lib/components/Divider.svelte
new file mode 100644
index 0000000..7045baf
--- /dev/null
+++ b/src/lib/components/Divider.svelte
@@ -0,0 +1 @@
+
diff --git a/src/lib/components/Footer.svelte b/src/lib/components/Footer.svelte
index b536fe9..f74d74f 100644
--- a/src/lib/components/Footer.svelte
+++ b/src/lib/components/Footer.svelte
@@ -9,9 +9,7 @@
diff --git a/src/lib/components/Icon.svelte b/src/lib/components/Icon.svelte
index e8fcb0a..11933a0 100644
--- a/src/lib/components/Icon.svelte
+++ b/src/lib/components/Icon.svelte
@@ -97,5 +97,23 @@
fill={stroke}
d="M2.5 11h19a.5.5 0 0 0 0-1h-19a.5.5 0 0 0 0 1zm19 3h-19a.5.5 0 0 0 0 1h19a.5.5 0 0 0 0-1z"
/>
+ {:else if type === IconType.Accept}
+
+ {:else if type === IconType.Decline}
+
{/if}
diff --git a/src/lib/components/Item.svelte b/src/lib/components/Item.svelte
index d2ac06a..78567c4 100644
--- a/src/lib/components/Item.svelte
+++ b/src/lib/components/Item.svelte
@@ -32,10 +32,10 @@
{item.picked && 'opacity-50'}"
>
-