From 254e053bd9696437104705c1c8dc682cf963a812 Mon Sep 17 00:00:00 2001 From: Christian Beutel <> Date: Sun, 8 Dec 2024 21:05:35 +0100 Subject: [PATCH] adds profile page --- db/migrations/1733580734_updated_users.go | 55 +++ .../1733580769_updated_users_anonymous.go | 179 +++++++ web/src/lib/components/nav_bar.svelte | 2 +- web/src/lib/i18n/locales/de.json | 1 + web/src/lib/i18n/locales/en.json | 1 + web/src/lib/i18n/locales/fr.json | 1 + web/src/lib/i18n/locales/hu.json | 1 + web/src/lib/i18n/locales/it.json | 1 + web/src/lib/i18n/locales/nl.json | 1 + web/src/lib/i18n/locales/pl.json | 1 + web/src/lib/i18n/locales/pt.json | 1 + web/src/lib/i18n/locales/zh.json | 1 + web/src/lib/models/user.ts | 2 + web/src/routes/profile/[id]/+layout.server.ts | 15 + web/src/routes/profile/[id]/+layout.svelte | 73 +++ web/src/routes/profile/[id]/+page.svelte | 443 +----------------- .../routes/profile/[id]/stats/+page.svelte | 400 ++++++++++++++++ .../routes/profile/[id]/{ => stats}/+page.ts | 3 +- .../settings/+layout.svelte} | 32 +- web/src/routes/settings/account/+page.svelte | 140 +----- web/src/routes/settings/display/+page.svelte | 254 ---------- web/src/routes/settings/export/+page.svelte | 71 ++- web/src/routes/settings/language/+page.svelte | 68 +++ web/src/routes/settings/map/+page.svelte | 208 ++++++++ web/src/routes/settings/profile/+page.svelte | 127 +++++ .../settings/{display => profile}/+page.ts | 0 26 files changed, 1243 insertions(+), 838 deletions(-) create mode 100644 db/migrations/1733580734_updated_users.go create mode 100644 db/migrations/1733580769_updated_users_anonymous.go create mode 100644 web/src/routes/profile/[id]/+layout.server.ts create mode 100644 web/src/routes/profile/[id]/+layout.svelte create mode 100644 web/src/routes/profile/[id]/stats/+page.svelte rename web/src/routes/profile/[id]/{ => stats}/+page.ts (92%) rename web/src/{lib/components/profile/settings.svelte => routes/settings/+layout.svelte} (51%) delete mode 100644 web/src/routes/settings/display/+page.svelte create mode 100644 web/src/routes/settings/language/+page.svelte create mode 100644 web/src/routes/settings/map/+page.svelte create mode 100644 web/src/routes/settings/profile/+page.svelte rename web/src/routes/settings/{display => profile}/+page.ts (100%) diff --git a/db/migrations/1733580734_updated_users.go b/db/migrations/1733580734_updated_users.go new file mode 100644 index 00000000..70402734 --- /dev/null +++ b/db/migrations/1733580734_updated_users.go @@ -0,0 +1,55 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/daos" + m "github.com/pocketbase/pocketbase/migrations" + "github.com/pocketbase/pocketbase/models/schema" +) + +func init() { + m.Register(func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_") + if err != nil { + return err + } + + // add + new_bio := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "pd2cq8sq", + "name": "bio", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": 10000, + "pattern": "" + } + }`), new_bio); err != nil { + return err + } + collection.Schema.AddField(new_bio) + + return dao.SaveCollection(collection) + }, func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_") + if err != nil { + return err + } + + // remove + collection.Schema.RemoveField("pd2cq8sq") + + return dao.SaveCollection(collection) + }) +} diff --git a/db/migrations/1733580769_updated_users_anonymous.go b/db/migrations/1733580769_updated_users_anonymous.go new file mode 100644 index 00000000..1396a7d0 --- /dev/null +++ b/db/migrations/1733580769_updated_users_anonymous.go @@ -0,0 +1,179 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/daos" + m "github.com/pocketbase/pocketbase/migrations" + "github.com/pocketbase/pocketbase/models/schema" +) + +func init() { + m.Register(func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("xku110v5a5xbufa") + if err != nil { + return err + } + + options := map[string]any{} + if err := json.Unmarshal([]byte(`{ + "query": "SELECT id, username, avatar, bio, created FROM users" + }`), &options); err != nil { + return err + } + collection.SetOptions(options) + + // remove + collection.Schema.RemoveField("femc0ok5") + + // remove + collection.Schema.RemoveField("aglcodpn") + + // add + new_username := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "tkxbpwxe", + "name": "username", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }`), new_username); err != nil { + return err + } + collection.Schema.AddField(new_username) + + // add + new_avatar := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "xs5qvkih", + "name": "avatar", + "type": "file", + "required": false, + "presentable": false, + "unique": false, + "options": { + "mimeTypes": [ + "image/jpeg", + "image/png", + "image/svg+xml", + "image/gif", + "image/webp" + ], + "thumbs": null, + "maxSelect": 1, + "maxSize": 5242880, + "protected": false + } + }`), new_avatar); err != nil { + return err + } + collection.Schema.AddField(new_avatar) + + // add + new_bio := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "agsa8h5z", + "name": "bio", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": 10000, + "pattern": "" + } + }`), new_bio); err != nil { + return err + } + collection.Schema.AddField(new_bio) + + return dao.SaveCollection(collection) + }, func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("xku110v5a5xbufa") + if err != nil { + return err + } + + options := map[string]any{} + if err := json.Unmarshal([]byte(`{ + "query": "SELECT id, username, avatar, created FROM users" + }`), &options); err != nil { + return err + } + collection.SetOptions(options) + + // add + del_username := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "femc0ok5", + "name": "username", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }`), del_username); err != nil { + return err + } + collection.Schema.AddField(del_username) + + // add + del_avatar := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "aglcodpn", + "name": "avatar", + "type": "file", + "required": false, + "presentable": false, + "unique": false, + "options": { + "mimeTypes": [ + "image/jpeg", + "image/png", + "image/svg+xml", + "image/gif", + "image/webp" + ], + "thumbs": null, + "maxSelect": 1, + "maxSize": 5242880, + "protected": false + } + }`), del_avatar); err != nil { + return err + } + collection.Schema.AddField(del_avatar) + + // remove + collection.Schema.RemoveField("tkxbpwxe") + + // remove + collection.Schema.RemoveField("xs5qvkih") + + // remove + collection.Schema.RemoveField("agsa8h5z") + + return dao.SaveCollection(collection) + }) +} diff --git a/web/src/lib/components/nav_bar.svelte b/web/src/lib/components/nav_bar.svelte index 1dedfe08..3a73a8ef 100644 --- a/web/src/lib/components/nav_bar.svelte +++ b/web/src/lib/components/nav_bar.svelte @@ -83,7 +83,7 @@ logout(); window.location.href = "/"; } else if (item.value == "settings") { - goto("/settings/account"); + goto("/settings/profile"); } } diff --git a/web/src/lib/i18n/locales/de.json b/web/src/lib/i18n/locales/de.json index b116a31b..39d690dc 100644 --- a/web/src/lib/i18n/locales/de.json +++ b/web/src/lib/i18n/locales/de.json @@ -95,6 +95,7 @@ "explore-some-trails": "Erkunden Sie einige Routen", "export": "Exportieren", "export-all-trails": "Alle Routen exportieren", + "favourite-sport": "", "features": "Features", "file-format": "Dateiformat", "file-too-big": "Datei {file} ist zu groß (max. {size})", diff --git a/web/src/lib/i18n/locales/en.json b/web/src/lib/i18n/locales/en.json index 8768383a..e37516fa 100644 --- a/web/src/lib/i18n/locales/en.json +++ b/web/src/lib/i18n/locales/en.json @@ -95,6 +95,7 @@ "explore-some-trails": "Explore some trails", "export": "Export", "export-all-trails": "Export all trails", + "favourite-sport": "Favourite sport", "features": "Features", "file-format": "File format", "file-too-big": "File {file} is too big (max. {size})", diff --git a/web/src/lib/i18n/locales/fr.json b/web/src/lib/i18n/locales/fr.json index 4bd7e578..ecef6241 100644 --- a/web/src/lib/i18n/locales/fr.json +++ b/web/src/lib/i18n/locales/fr.json @@ -95,6 +95,7 @@ "explore-some-trails": "Explorer certains itinéraires", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "Fonctionnalités", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/hu.json b/web/src/lib/i18n/locales/hu.json index 27a2a9ab..2f4b0263 100644 --- a/web/src/lib/i18n/locales/hu.json +++ b/web/src/lib/i18n/locales/hu.json @@ -95,6 +95,7 @@ "explore-some-trails": "Fedezzen fel néhány ösvényt", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "Jellemzők", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/it.json b/web/src/lib/i18n/locales/it.json index 2f9ecffd..e8f50f22 100644 --- a/web/src/lib/i18n/locales/it.json +++ b/web/src/lib/i18n/locales/it.json @@ -95,6 +95,7 @@ "explore-some-trails": "Esplora alcuni percorsi", "export": "Esporta", "export-all-trails": "", + "favourite-sport": "", "features": "Caratteristiche", "file-format": "Formato del file", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/nl.json b/web/src/lib/i18n/locales/nl.json index 9621936f..8d8daa9c 100644 --- a/web/src/lib/i18n/locales/nl.json +++ b/web/src/lib/i18n/locales/nl.json @@ -95,6 +95,7 @@ "explore-some-trails": "Verken enkele wandelroutes", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "Kenmerken", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/pl.json b/web/src/lib/i18n/locales/pl.json index 690d7293..1551a80e 100644 --- a/web/src/lib/i18n/locales/pl.json +++ b/web/src/lib/i18n/locales/pl.json @@ -95,6 +95,7 @@ "explore-some-trails": "Eksploruj różne ścieżki", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "Funkcje", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/pt.json b/web/src/lib/i18n/locales/pt.json index 6b479b9d..8b4dbc79 100644 --- a/web/src/lib/i18n/locales/pt.json +++ b/web/src/lib/i18n/locales/pt.json @@ -95,6 +95,7 @@ "explore-some-trails": "Explore algumas trilhas", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "Características", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/i18n/locales/zh.json b/web/src/lib/i18n/locales/zh.json index a429316d..8ed40675 100644 --- a/web/src/lib/i18n/locales/zh.json +++ b/web/src/lib/i18n/locales/zh.json @@ -95,6 +95,7 @@ "explore-some-trails": "探索行程", "export": "", "export-all-trails": "", + "favourite-sport": "", "features": "特性", "file-format": "", "file-too-big": "", diff --git a/web/src/lib/models/user.ts b/web/src/lib/models/user.ts index 3be3c99d..f30f3066 100644 --- a/web/src/lib/models/user.ts +++ b/web/src/lib/models/user.ts @@ -6,6 +6,7 @@ export type User = { email?: string, password: string, avatar?: string; + bio?: string; language?: string; created?: string; } @@ -14,5 +15,6 @@ export type UserAnonymous = { id: string, username?: string, avatar?: string; + bio?: string; created?: string; } \ No newline at end of file diff --git a/web/src/routes/profile/[id]/+layout.server.ts b/web/src/routes/profile/[id]/+layout.server.ts new file mode 100644 index 00000000..1d174a56 --- /dev/null +++ b/web/src/routes/profile/[id]/+layout.server.ts @@ -0,0 +1,15 @@ +import { users_show } from "$lib/stores/user_store"; +import { error, type ServerLoad } from "@sveltejs/kit"; + +export const load: ServerLoad = async ({ params, locals, fetch }) => { + + if(!params.id) { + error(404, "Not found") + } + + const user = await users_show(params.id, fetch); + + const isOwnProfile = params.id === locals.user?.id; + + return { user, isOwnProfile } +}; \ No newline at end of file diff --git a/web/src/routes/profile/[id]/+layout.svelte b/web/src/routes/profile/[id]/+layout.svelte new file mode 100644 index 00000000..0fc237d2 --- /dev/null +++ b/web/src/routes/profile/[id]/+layout.svelte @@ -0,0 +1,73 @@ + + +
+ Joined: + {new Date(data.user.created ?? "").toLocaleDateString( + undefined, + { + month: "2-digit", + day: "2-digit", + year: "numeric", + timeZone: "UTC", + }, + )} +
+0
+Followers
+0
+Following
+- Joined: - {new Date(data.user.created ?? "").toLocaleDateString( - undefined, - { - month: "2-digit", - day: "2-digit", - year: "numeric", - timeZone: "UTC", - }, - )} -
-{$summitLogs.length}
-{formatDistance(totalDistance)}
-- {formatTimeHHMM(totalDuration / 60)} -
-- {formatElevation(totalElevationGain)} -
-- {formatElevation(totalElevationLoss)} -
-{formatSpeed(averageSpeed)}
-{data.user.bio}
+ {:else if data.isOwnProfile} + + Add Bio + {/if}{$summitLogs.length}
+{formatDistance(totalDistance)}
++ {formatTimeHHMM(totalDuration / 60)} +
+{formatSpeed(averageSpeed)}
++ {formatElevation(totalElevationGain)} +
++ {formatElevation(totalElevationLoss)} +
+