diff --git a/apps/www/migrations/0015_adorable_glorian.sql b/apps/www/migrations/0015_adorable_glorian.sql new file mode 100644 index 00000000..c412a4cc --- /dev/null +++ b/apps/www/migrations/0015_adorable_glorian.sql @@ -0,0 +1 @@ +ALTER TABLE `user` ADD `alt_email` text; \ No newline at end of file diff --git a/apps/www/migrations/0016_nasty_princess_powerful.sql b/apps/www/migrations/0016_nasty_princess_powerful.sql new file mode 100644 index 00000000..34bb06d5 --- /dev/null +++ b/apps/www/migrations/0016_nasty_princess_powerful.sql @@ -0,0 +1,17 @@ +PRAGMA foreign_keys=OFF;--> statement-breakpoint +CREATE TABLE `__new_user` ( + `id` text PRIMARY KEY NOT NULL, + `name` text NOT NULL, + `email` text NOT NULL, + `feide_id` text, + `role` text DEFAULT 'normal' NOT NULL, + `additional_beers` integer DEFAULT 0 NOT NULL, + `alt_email` text DEFAULT '' +); +--> statement-breakpoint +INSERT INTO `__new_user`("id", "name", "email", "feide_id", "role", "additional_beers", "alt_email") SELECT "id", "name", "email", "feide_id", "role", "additional_beers", "alt_email" FROM `user`;--> statement-breakpoint +DROP TABLE `user`;--> statement-breakpoint +ALTER TABLE `__new_user` RENAME TO `user`;--> statement-breakpoint +PRAGMA foreign_keys=ON;--> statement-breakpoint +CREATE UNIQUE INDEX `email_idx` ON `user` (`email`);--> statement-breakpoint +CREATE UNIQUE INDEX `feide_id_idx` ON `user` (`feide_id`); \ No newline at end of file diff --git a/apps/www/migrations/meta/0015_snapshot.json b/apps/www/migrations/meta/0015_snapshot.json new file mode 100644 index 00000000..77f16ee9 --- /dev/null +++ b/apps/www/migrations/meta/0015_snapshot.json @@ -0,0 +1,564 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "43ce48b8-c491-4e7e-a1b1-f021301b3032", + "prevId": "829e0db2-f6a7-40d1-8d6c-119515a76118", + "tables": { + "claimed_credits": { + "name": "claimed_credits", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "product_id": { + "name": "product_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credit_cost": { + "name": "credit_cost", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "claimed_credits_user_id_user_id_fk": { + "name": "claimed_credits_user_id_user_id_fk", + "tableFrom": "claimed_credits", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event": { + "name": "event", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "date": { + "name": "date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "group": { + "name": "group", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitation": { + "name": "invitation", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification": { + "name": "notification", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "archived_at": { + "name": "archived_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_notifications_user_id": { + "name": "idx_notifications_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_notifications_archived_at": { + "name": "idx_notifications_archived_at", + "columns": [ + "archived_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "notification_user_id_user_id_fk": { + "name": "notification_user_id_user_id_fk", + "tableFrom": "notification", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "session": { + "name": "session", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "shift": { + "name": "shift", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "start_at": { + "name": "start_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "end_at": { + "name": "end_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "shift_event_id_event_id_fk": { + "name": "shift_event_id_event_id_fk", + "tableFrom": "shift", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_shift": { + "name": "user_shift", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "shift_id": { + "name": "shift_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_beer_claimed": { + "name": "is_beer_claimed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'accepted'" + } + }, + "indexes": {}, + "foreignKeys": { + "user_shift_user_id_user_id_fk": { + "name": "user_shift_user_id_user_id_fk", + "tableFrom": "user_shift", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_shift_shift_id_shift_id_fk": { + "name": "user_shift_shift_id_shift_id_fk", + "tableFrom": "user_shift", + "tableTo": "shift", + "columnsFrom": [ + "shift_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users_groups": { + "name": "users_groups", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_groups_user_id_user_id_fk": { + "name": "users_groups_user_id_user_id_fk", + "tableFrom": "users_groups", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "users_groups_group_id_group_id_fk": { + "name": "users_groups_group_id_group_id_fk", + "tableFrom": "users_groups", + "tableTo": "group", + "columnsFrom": [ + "group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "feide_id": { + "name": "feide_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'normal'" + }, + "additional_beers": { + "name": "additional_beers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "alt_email": { + "name": "alt_email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": true + }, + "feide_id_idx": { + "name": "feide_id_idx", + "columns": [ + "feide_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/www/migrations/meta/0016_snapshot.json b/apps/www/migrations/meta/0016_snapshot.json new file mode 100644 index 00000000..a9bbbc41 --- /dev/null +++ b/apps/www/migrations/meta/0016_snapshot.json @@ -0,0 +1,565 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "d6fb2eb6-0085-4aeb-aa4a-360c72f5f49e", + "prevId": "43ce48b8-c491-4e7e-a1b1-f021301b3032", + "tables": { + "claimed_credits": { + "name": "claimed_credits", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "product_id": { + "name": "product_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credit_cost": { + "name": "credit_cost", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "claimed_credits_user_id_user_id_fk": { + "name": "claimed_credits_user_id_user_id_fk", + "tableFrom": "claimed_credits", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event": { + "name": "event", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "date": { + "name": "date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "group": { + "name": "group", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitation": { + "name": "invitation", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "notification": { + "name": "notification", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "archived_at": { + "name": "archived_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_notifications_user_id": { + "name": "idx_notifications_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_notifications_archived_at": { + "name": "idx_notifications_archived_at", + "columns": [ + "archived_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "notification_user_id_user_id_fk": { + "name": "notification_user_id_user_id_fk", + "tableFrom": "notification", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "session": { + "name": "session", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "shift": { + "name": "shift", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "start_at": { + "name": "start_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "end_at": { + "name": "end_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "shift_event_id_event_id_fk": { + "name": "shift_event_id_event_id_fk", + "tableFrom": "shift", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_shift": { + "name": "user_shift", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "shift_id": { + "name": "shift_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_beer_claimed": { + "name": "is_beer_claimed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'accepted'" + } + }, + "indexes": {}, + "foreignKeys": { + "user_shift_user_id_user_id_fk": { + "name": "user_shift_user_id_user_id_fk", + "tableFrom": "user_shift", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_shift_shift_id_shift_id_fk": { + "name": "user_shift_shift_id_shift_id_fk", + "tableFrom": "user_shift", + "tableTo": "shift", + "columnsFrom": [ + "shift_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users_groups": { + "name": "users_groups", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "users_groups_user_id_user_id_fk": { + "name": "users_groups_user_id_user_id_fk", + "tableFrom": "users_groups", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "users_groups_group_id_group_id_fk": { + "name": "users_groups_group_id_group_id_fk", + "tableFrom": "users_groups", + "tableTo": "group", + "columnsFrom": [ + "group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "feide_id": { + "name": "feide_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'normal'" + }, + "additional_beers": { + "name": "additional_beers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "alt_email": { + "name": "alt_email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + } + }, + "indexes": { + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": true + }, + "feide_id_idx": { + "name": "feide_id_idx", + "columns": [ + "feide_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/www/migrations/meta/_journal.json b/apps/www/migrations/meta/_journal.json index 758c3510..2b52aff3 100644 --- a/apps/www/migrations/meta/_journal.json +++ b/apps/www/migrations/meta/_journal.json @@ -106,6 +106,20 @@ "when": 1746103110959, "tag": "0014_wandering_vulture", "breakpoints": true + }, + { + "idx": 15, + "version": "6", + "when": 1748776203402, + "tag": "0015_adorable_glorian", + "breakpoints": true + }, + { + "idx": 16, + "version": "6", + "when": 1749073238658, + "tag": "0016_nasty_princess_powerful", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/www/src/lib/components/cards/UserCard.svelte b/apps/www/src/lib/components/cards/UserCard.svelte index 4dbd8f8e..65a575c3 100644 --- a/apps/www/src/lib/components/cards/UserCard.svelte +++ b/apps/www/src/lib/components/cards/UserCard.svelte @@ -31,7 +31,6 @@ onkeydown={handleKeyDown} aria-label={`Click to view details of ${user.name}`} > -
{initials(user.name)} @@ -52,7 +51,12 @@ {/if}

- {user.email} + + {user.altEmail || user.email} +

diff --git a/apps/www/src/lib/components/portal/Header.svelte b/apps/www/src/lib/components/portal/Header.svelte index 31f1fd8d..2f4f8326 100644 --- a/apps/www/src/lib/components/portal/Header.svelte +++ b/apps/www/src/lib/components/portal/Header.svelte @@ -35,6 +35,10 @@ name: 'Brukere', href: '/portal/brukere' }, + { + name: 'Min Profil', + href: '/portal/profil' + }, { name: 'Admin', href: '/portal/admin', diff --git a/apps/www/src/lib/db/schemas/users.ts b/apps/www/src/lib/db/schemas/users.ts index 1225ec44..c70b42ec 100644 --- a/apps/www/src/lib/db/schemas/users.ts +++ b/apps/www/src/lib/db/schemas/users.ts @@ -15,7 +15,8 @@ export const users = sqliteTable( role: text({ enum: ['board', 'normal'] }) .notNull() .default('normal'), - additionalBeers: integer().default(0).notNull() + additionalBeers: integer().default(0).notNull(), + altEmail: text().default('') }, (t) => [uniqueIndex('email_idx').on(t.email), uniqueIndex('feide_id_idx').on(t.feideId)] ); diff --git a/apps/www/src/lib/services/email.service.tsx b/apps/www/src/lib/services/email.service.tsx index 9742c789..6018c58e 100644 --- a/apps/www/src/lib/services/email.service.tsx +++ b/apps/www/src/lib/services/email.service.tsx @@ -7,6 +7,7 @@ import { } from '@programmerbar/emails'; import type { CreateEmailOptions, Resend } from 'resend'; import { render } from '@react-email/render'; +import { formatDate, normalDate } from '$lib/date'; const PROGRAMMERBAR_EMAIL = 'styret@programmerbar.no'; const FROM_EMAIL = 'ikkesvar@programmer.bar'; @@ -49,19 +50,9 @@ function generateICS(shift: { }): string { const uid = shift.id; - const formatDate = (dateStr: string) => { - const date = new Date(dateStr); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - return `${year}${month}${day}T${hours}${minutes}${seconds}`; - }; const dtstamp = formatDate(new Date().toISOString()); - const dtstart = formatDate(shift.startAt); - const dtend = formatDate(shift.endAt); + const dtstart = normalDate(shift.startAt); + const dtend = normalDate(shift.endAt); return `BEGIN:VCALENDAR VERSION:2.0 diff --git a/apps/www/src/lib/services/user.service.ts b/apps/www/src/lib/services/user.service.ts index 5c1f83aa..47d7a38b 100644 --- a/apps/www/src/lib/services/user.service.ts +++ b/apps/www/src/lib/services/user.service.ts @@ -36,6 +36,15 @@ export class UserService { .then((rows) => rows[0]); } + async updateAltEmail(userId: string, email: string) { + return await this.#db + .update(users) + .set({ altEmail: email }) + .where(eq(users.id, userId)) + .returning() + .then((rows) => rows[0]); + } + async findById(userId: string) { const user = await this.#db .select() diff --git a/apps/www/src/lib/validators.ts b/apps/www/src/lib/validators.ts index b4c4f8c4..5b912283 100644 --- a/apps/www/src/lib/validators.ts +++ b/apps/www/src/lib/validators.ts @@ -23,10 +23,13 @@ export const CreateInvitationSchema = z.object({ email: z.string().email() }); +export const isValidEmail = (x: unknown): boolean => z.string().email().safeParse(x).success; + export const CreateEmailShiftSchema = z.object({ user: z.object({ name: z.string().min(1), - email: z.string().email() + email: z.string().email(), + altEmail: z.string().email() }), shift: z.object({ startAt: z.coerce.date(), diff --git a/apps/www/src/routes/api/events/+server.ts b/apps/www/src/routes/api/events/+server.ts index f0c732b5..1abf53d4 100644 --- a/apps/www/src/routes/api/events/+server.ts +++ b/apps/www/src/routes/api/events/+server.ts @@ -43,7 +43,7 @@ export const POST: RequestHandler = async ({ request, locals }) => { const emailData: ShiftEmailProps = { user: { name: user.name || 'Frivillig', - email: user.email + email: user.altEmail || user.email }, shift: { id: shift.id, diff --git a/apps/www/src/routes/portal/profil/+page.server.ts b/apps/www/src/routes/portal/profil/+page.server.ts new file mode 100644 index 00000000..f86d398e --- /dev/null +++ b/apps/www/src/routes/portal/profil/+page.server.ts @@ -0,0 +1,45 @@ +import { fail, redirect } from '@sveltejs/kit'; +import { isValidEmail } from '$lib/validators'; +import type { Actions, PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ locals }) => { + if (!locals.user) { + throw redirect(307, '/login'); + } + const user = await locals.userService.findById(locals.user.id); + return { + user + }; +}; + +export const actions: Actions = { + save: async ({ request, locals }) => { + if (!locals.user) { + throw redirect(307, '/login'); + } + const data = await request.formData(); + const altEmail = data.get('altEmail') as string; + + if (!isValidEmail(altEmail)) { + return fail(400, { + success: false, + message: 'Ugyldig e-postadresse', + altEmail + }); + } + + const success = await locals.userService.updateAltEmail(locals.user.id, altEmail); + if (!success) { + return fail(500, { + success: false, + message: 'Kunne ikke oppdatere e-postadresse', + altEmail + }); + } + + return { + success: true, + message: 'E-postadresse er oppdatert!' + }; + } +}; diff --git a/apps/www/src/routes/portal/profil/+page.svelte b/apps/www/src/routes/portal/profil/+page.svelte new file mode 100644 index 00000000..175a79f6 --- /dev/null +++ b/apps/www/src/routes/portal/profil/+page.svelte @@ -0,0 +1,63 @@ + + + + Min Profil + +
+
+
+
+
+

Profilinnstillinger

+

Oppdater din informasjon og innstillinger

+
+
+
+
+ {#if form?.message} +
+

{form.message}

+
+ {/if} +
+
+
+
+

+ Kontaktinformasjon +

+

Oppdater din alternative e-postadresse

+
+
+ +
+
+
+
+ +
+
+
+
+