From 5d3a24fb645e230bcbc78d3b80d42186ec2eb202 Mon Sep 17 00:00:00 2001 From: Anton Tranelis Date: Tue, 16 Dec 2025 16:56:38 +0100 Subject: [PATCH] refactored tabs, offers and need --- .../collections/attestations_component.json | 28 ++++ .../development/snapshot/collections/tab.json | 28 ++++ .../snapshot/collections/tab_items.json | 28 ++++ .../snapshot/collections/tabs.json | 28 ++++ .../snapshot/collections/tags_component.json | 28 ++++ .../attestations_component/heading.json | 43 ++++++ .../attestations_component/hideWhenEmpty.json | 45 ++++++ .../fields/attestations_component/id.json | 45 ++++++ .../development/snapshot/fields/tab/icon.json | 43 ++++++ .../development/snapshot/fields/tab/id.json | 45 ++++++ .../snapshot/fields/tab/items.json | 32 +++++ .../development/snapshot/fields/tab/sort.json | 43 ++++++ .../snapshot/fields/tab/tabs_id.json | 43 ++++++ .../snapshot/fields/tab/title.json | 43 ++++++ .../snapshot/fields/tab_items/collection.json | 43 ++++++ .../snapshot/fields/tab_items/id.json | 43 ++++++ .../snapshot/fields/tab_items/item.json | 43 ++++++ .../snapshot/fields/tab_items/sort.json | 43 ++++++ .../snapshot/fields/tab_items/tab_id.json | 43 ++++++ .../snapshot/fields/tabs/icon_as_labels.json | 45 ++++++ .../development/snapshot/fields/tabs/id.json | 45 ++++++ .../snapshot/fields/tabs/tabs.json | 33 +++++ .../fields/tags_component/dataField.json | 54 +++++++ .../fields/tags_component/heading.json | 43 ++++++ .../fields/tags_component/hideWhenEmpty.json | 45 ++++++ .../snapshot/fields/tags_component/id.json | 45 ++++++ .../fields/tags_component/placeholder.json | 43 ++++++ .../snapshot/relations/tab/tabs_id.json | 25 ++++ .../snapshot/relations/tab_items/item.json | 27 ++++ .../snapshot/relations/tab_items/tab_id.json | 25 ++++ .../relations/types_profileTemplate/item.json | 5 +- lib/src/Components/Input/Autocomplete.tsx | 5 +- lib/src/Components/Profile/ProfileView.tsx | 7 +- .../Subcomponents/AttestationsView.tsx | 93 ++++++++++++ .../Profile/Subcomponents/ContactInfoView.tsx | 2 +- .../Subcomponents/CrowdfundingView.tsx | 2 +- .../Profile/Subcomponents/GalleryView.tsx | 2 +- .../Subcomponents/GroupSubHeaderView.tsx | 2 +- .../Profile/Subcomponents/InviteLinkView.tsx | 2 +- .../Subcomponents/ProfileStartEndView.tsx | 2 +- .../Profile/Subcomponents/ProfileTagsForm.tsx | 41 ++++++ .../Profile/Subcomponents/ProfileTagsView.tsx | 56 ++++++++ .../Profile/Subcomponents/ProfileTextView.tsx | 2 +- .../Profile/Subcomponents/RelationsView.tsx | 2 +- .../Subcomponents/TabsContainerForm.tsx | 133 ++++++++++++++++++ .../Subcomponents/TabsContainerView.tsx | 115 +++++++++++++++ .../Profile/Subcomponents/TagsWidget.tsx | 2 +- .../Components/Profile/Templates/FlexForm.tsx | 9 +- .../Components/Profile/Templates/FlexView.tsx | 9 +- .../Profile/hooks/useAttestations.ts | 16 +++ package-lock.json | 52 ++----- 51 files changed, 1667 insertions(+), 59 deletions(-) create mode 100644 backend/directus-config/development/snapshot/collections/attestations_component.json create mode 100644 backend/directus-config/development/snapshot/collections/tab.json create mode 100644 backend/directus-config/development/snapshot/collections/tab_items.json create mode 100644 backend/directus-config/development/snapshot/collections/tabs.json create mode 100644 backend/directus-config/development/snapshot/collections/tags_component.json create mode 100644 backend/directus-config/development/snapshot/fields/attestations_component/heading.json create mode 100644 backend/directus-config/development/snapshot/fields/attestations_component/hideWhenEmpty.json create mode 100644 backend/directus-config/development/snapshot/fields/attestations_component/id.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/icon.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/id.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/items.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/sort.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/tabs_id.json create mode 100644 backend/directus-config/development/snapshot/fields/tab/title.json create mode 100644 backend/directus-config/development/snapshot/fields/tab_items/collection.json create mode 100644 backend/directus-config/development/snapshot/fields/tab_items/id.json create mode 100644 backend/directus-config/development/snapshot/fields/tab_items/item.json create mode 100644 backend/directus-config/development/snapshot/fields/tab_items/sort.json create mode 100644 backend/directus-config/development/snapshot/fields/tab_items/tab_id.json create mode 100644 backend/directus-config/development/snapshot/fields/tabs/icon_as_labels.json create mode 100644 backend/directus-config/development/snapshot/fields/tabs/id.json create mode 100644 backend/directus-config/development/snapshot/fields/tabs/tabs.json create mode 100644 backend/directus-config/development/snapshot/fields/tags_component/dataField.json create mode 100644 backend/directus-config/development/snapshot/fields/tags_component/heading.json create mode 100644 backend/directus-config/development/snapshot/fields/tags_component/hideWhenEmpty.json create mode 100644 backend/directus-config/development/snapshot/fields/tags_component/id.json create mode 100644 backend/directus-config/development/snapshot/fields/tags_component/placeholder.json create mode 100644 backend/directus-config/development/snapshot/relations/tab/tabs_id.json create mode 100644 backend/directus-config/development/snapshot/relations/tab_items/item.json create mode 100644 backend/directus-config/development/snapshot/relations/tab_items/tab_id.json create mode 100644 lib/src/Components/Profile/Subcomponents/AttestationsView.tsx create mode 100644 lib/src/Components/Profile/Subcomponents/ProfileTagsForm.tsx create mode 100644 lib/src/Components/Profile/Subcomponents/ProfileTagsView.tsx create mode 100644 lib/src/Components/Profile/Subcomponents/TabsContainerForm.tsx create mode 100644 lib/src/Components/Profile/Subcomponents/TabsContainerView.tsx create mode 100644 lib/src/Components/Profile/hooks/useAttestations.ts diff --git a/backend/directus-config/development/snapshot/collections/attestations_component.json b/backend/directus-config/development/snapshot/collections/attestations_component.json new file mode 100644 index 00000000..688d5975 --- /dev/null +++ b/backend/directus-config/development/snapshot/collections/attestations_component.json @@ -0,0 +1,28 @@ +{ + "collection": "attestations_component", + "meta": { + "accountability": "all", + "archive_app_filter": true, + "archive_field": null, + "archive_value": null, + "collapse": "open", + "collection": "attestations_component", + "color": null, + "display_template": null, + "group": "UI_Components", + "hidden": false, + "icon": "favorite", + "item_duplication_fields": null, + "note": null, + "preview_url": null, + "singleton": false, + "sort": 11, + "sort_field": null, + "translations": null, + "unarchive_value": null, + "versioning": false + }, + "schema": { + "name": "attestations_component" + } +} diff --git a/backend/directus-config/development/snapshot/collections/tab.json b/backend/directus-config/development/snapshot/collections/tab.json new file mode 100644 index 00000000..ec4e3975 --- /dev/null +++ b/backend/directus-config/development/snapshot/collections/tab.json @@ -0,0 +1,28 @@ +{ + "collection": "tab", + "meta": { + "collection": "tab", + "icon": "tab", + "note": null, + "display_template": "{{title}}", + "hidden": false, + "singleton": false, + "translations": null, + "archive_field": null, + "archive_app_filter": true, + "archive_value": null, + "unarchive_value": null, + "sort_field": "sort", + "accountability": "all", + "color": null, + "item_duplication_fields": null, + "sort": null, + "group": null, + "collapse": "open", + "preview_url": null, + "versioning": false + }, + "schema": { + "name": "tab" + } +} diff --git a/backend/directus-config/development/snapshot/collections/tab_items.json b/backend/directus-config/development/snapshot/collections/tab_items.json new file mode 100644 index 00000000..a1ebcce7 --- /dev/null +++ b/backend/directus-config/development/snapshot/collections/tab_items.json @@ -0,0 +1,28 @@ +{ + "collection": "tab_items", + "meta": { + "collection": "tab_items", + "icon": "import_export", + "note": null, + "display_template": null, + "hidden": true, + "singleton": false, + "translations": null, + "archive_field": null, + "archive_app_filter": true, + "archive_value": null, + "unarchive_value": null, + "sort_field": "sort", + "accountability": "all", + "color": null, + "item_duplication_fields": null, + "sort": null, + "group": null, + "collapse": "open", + "preview_url": null, + "versioning": false + }, + "schema": { + "name": "tab_items" + } +} diff --git a/backend/directus-config/development/snapshot/collections/tabs.json b/backend/directus-config/development/snapshot/collections/tabs.json new file mode 100644 index 00000000..59e0d114 --- /dev/null +++ b/backend/directus-config/development/snapshot/collections/tabs.json @@ -0,0 +1,28 @@ +{ + "collection": "tabs", + "meta": { + "accountability": "all", + "archive_app_filter": true, + "archive_field": null, + "archive_value": null, + "collapse": "open", + "collection": "tabs", + "color": null, + "display_template": null, + "group": "UI_Components", + "hidden": false, + "icon": "tab", + "item_duplication_fields": null, + "note": null, + "preview_url": null, + "singleton": false, + "sort": 12, + "sort_field": null, + "translations": null, + "unarchive_value": null, + "versioning": false + }, + "schema": { + "name": "tabs" + } +} diff --git a/backend/directus-config/development/snapshot/collections/tags_component.json b/backend/directus-config/development/snapshot/collections/tags_component.json new file mode 100644 index 00000000..d70aefee --- /dev/null +++ b/backend/directus-config/development/snapshot/collections/tags_component.json @@ -0,0 +1,28 @@ +{ + "collection": "tags_component", + "meta": { + "accountability": "all", + "archive_app_filter": true, + "archive_field": null, + "archive_value": null, + "collapse": "open", + "collection": "tags_component", + "color": null, + "display_template": null, + "group": "UI_Components", + "hidden": false, + "icon": "sell", + "item_duplication_fields": null, + "note": null, + "preview_url": null, + "singleton": false, + "sort": 10, + "sort_field": null, + "translations": null, + "unarchive_value": null, + "versioning": false + }, + "schema": { + "name": "tags_component" + } +} diff --git a/backend/directus-config/development/snapshot/fields/attestations_component/heading.json b/backend/directus-config/development/snapshot/fields/attestations_component/heading.json new file mode 100644 index 00000000..486bbcce --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/attestations_component/heading.json @@ -0,0 +1,43 @@ +{ + "collection": "attestations_component", + "field": "heading", + "type": "string", + "meta": { + "collection": "attestations_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "heading", + "group": null, + "hidden": false, + "interface": "input", + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 2, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "heading", + "table": "attestations_component", + "data_type": "character varying", + "default_value": "Trust", + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/attestations_component/hideWhenEmpty.json b/backend/directus-config/development/snapshot/fields/attestations_component/hideWhenEmpty.json new file mode 100644 index 00000000..f4d25333 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/attestations_component/hideWhenEmpty.json @@ -0,0 +1,45 @@ +{ + "collection": "attestations_component", + "field": "hideWhenEmpty", + "type": "boolean", + "meta": { + "collection": "attestations_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "hideWhenEmpty", + "group": null, + "hidden": false, + "interface": "boolean", + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 3, + "special": [ + "cast-boolean" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "hideWhenEmpty", + "table": "attestations_component", + "data_type": "boolean", + "default_value": true, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/attestations_component/id.json b/backend/directus-config/development/snapshot/fields/attestations_component/id.json new file mode 100644 index 00000000..d543da4b --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/attestations_component/id.json @@ -0,0 +1,45 @@ +{ + "collection": "attestations_component", + "field": "id", + "type": "uuid", + "meta": { + "collection": "attestations_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "id", + "group": null, + "hidden": true, + "interface": "input", + "note": null, + "options": null, + "readonly": true, + "required": false, + "sort": 1, + "special": [ + "uuid" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "id", + "table": "attestations_component", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": true, + "is_indexed": false, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/icon.json b/backend/directus-config/development/snapshot/fields/tab/icon.json new file mode 100644 index 00000000..3d638824 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/icon.json @@ -0,0 +1,43 @@ +{ + "collection": "tab", + "field": "icon", + "type": "string", + "meta": { + "collection": "tab", + "conditions": null, + "display": null, + "display_options": null, + "field": "icon", + "group": null, + "hidden": false, + "interface": "input", + "note": "Optional emoji or icon for the tab", + "options": null, + "readonly": false, + "required": false, + "sort": 3, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "icon", + "table": "tab", + "data_type": "character varying", + "default_value": null, + "max_length": 50, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/id.json b/backend/directus-config/development/snapshot/fields/tab/id.json new file mode 100644 index 00000000..3388bfa2 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/id.json @@ -0,0 +1,45 @@ +{ + "collection": "tab", + "field": "id", + "type": "uuid", + "meta": { + "collection": "tab", + "conditions": null, + "display": null, + "display_options": null, + "field": "id", + "group": null, + "hidden": true, + "interface": "input", + "note": null, + "options": null, + "readonly": true, + "required": false, + "sort": 1, + "special": [ + "uuid" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "id", + "table": "tab", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": true, + "is_indexed": false, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/items.json b/backend/directus-config/development/snapshot/fields/tab/items.json new file mode 100644 index 00000000..6ad7a93e --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/items.json @@ -0,0 +1,32 @@ +{ + "collection": "tab", + "field": "items", + "type": "alias", + "meta": { + "collection": "tab", + "conditions": null, + "display": "related-values", + "display_options": { + "template": "{{collection}}" + }, + "field": "items", + "group": null, + "hidden": false, + "interface": "list-m2a", + "note": "Components inside this tab", + "options": { + "enableCreate": true, + "enableSelect": true + }, + "readonly": false, + "required": false, + "sort": 6, + "special": [ + "m2a" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/sort.json b/backend/directus-config/development/snapshot/fields/tab/sort.json new file mode 100644 index 00000000..144a8cf4 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/sort.json @@ -0,0 +1,43 @@ +{ + "collection": "tab", + "field": "sort", + "type": "integer", + "meta": { + "collection": "tab", + "conditions": null, + "display": null, + "display_options": null, + "field": "sort", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 4, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "sort", + "table": "tab", + "data_type": "integer", + "default_value": null, + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/tabs_id.json b/backend/directus-config/development/snapshot/fields/tab/tabs_id.json new file mode 100644 index 00000000..82643412 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/tabs_id.json @@ -0,0 +1,43 @@ +{ + "collection": "tab", + "field": "tabs_id", + "type": "uuid", + "meta": { + "collection": "tab", + "conditions": null, + "display": null, + "display_options": null, + "field": "tabs_id", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 5, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "tabs_id", + "table": "tab", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": "tabs", + "foreign_key_column": "id" + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab/title.json b/backend/directus-config/development/snapshot/fields/tab/title.json new file mode 100644 index 00000000..c2d5988a --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab/title.json @@ -0,0 +1,43 @@ +{ + "collection": "tab", + "field": "title", + "type": "string", + "meta": { + "collection": "tab", + "conditions": null, + "display": null, + "display_options": null, + "field": "title", + "group": null, + "hidden": false, + "interface": "input", + "note": "Tab title displayed in the tab header", + "options": null, + "readonly": false, + "required": true, + "sort": 2, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "title", + "table": "tab", + "data_type": "character varying", + "default_value": null, + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab_items/collection.json b/backend/directus-config/development/snapshot/fields/tab_items/collection.json new file mode 100644 index 00000000..4a8e1af0 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab_items/collection.json @@ -0,0 +1,43 @@ +{ + "collection": "tab_items", + "field": "collection", + "type": "string", + "meta": { + "collection": "tab_items", + "conditions": null, + "display": null, + "display_options": null, + "field": "collection", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 4, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "collection", + "table": "tab_items", + "data_type": "character varying", + "default_value": null, + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab_items/id.json b/backend/directus-config/development/snapshot/fields/tab_items/id.json new file mode 100644 index 00000000..aa5fde48 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab_items/id.json @@ -0,0 +1,43 @@ +{ + "collection": "tab_items", + "field": "id", + "type": "integer", + "meta": { + "collection": "tab_items", + "conditions": null, + "display": null, + "display_options": null, + "field": "id", + "group": null, + "hidden": true, + "interface": "input", + "note": null, + "options": null, + "readonly": true, + "required": false, + "sort": 1, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "id", + "table": "tab_items", + "data_type": "integer", + "default_value": "nextval('tab_items_id_seq'::regclass)", + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": false, + "is_unique": true, + "is_indexed": false, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": true, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab_items/item.json b/backend/directus-config/development/snapshot/fields/tab_items/item.json new file mode 100644 index 00000000..43105dd1 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab_items/item.json @@ -0,0 +1,43 @@ +{ + "collection": "tab_items", + "field": "item", + "type": "string", + "meta": { + "collection": "tab_items", + "conditions": null, + "display": null, + "display_options": null, + "field": "item", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 3, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "item", + "table": "tab_items", + "data_type": "character varying", + "default_value": null, + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab_items/sort.json b/backend/directus-config/development/snapshot/fields/tab_items/sort.json new file mode 100644 index 00000000..3cc042c4 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab_items/sort.json @@ -0,0 +1,43 @@ +{ + "collection": "tab_items", + "field": "sort", + "type": "integer", + "meta": { + "collection": "tab_items", + "conditions": null, + "display": null, + "display_options": null, + "field": "sort", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 5, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "sort", + "table": "tab_items", + "data_type": "integer", + "default_value": null, + "max_length": null, + "numeric_precision": 32, + "numeric_scale": 0, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tab_items/tab_id.json b/backend/directus-config/development/snapshot/fields/tab_items/tab_id.json new file mode 100644 index 00000000..9f743425 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tab_items/tab_id.json @@ -0,0 +1,43 @@ +{ + "collection": "tab_items", + "field": "tab_id", + "type": "uuid", + "meta": { + "collection": "tab_items", + "conditions": null, + "display": null, + "display_options": null, + "field": "tab_id", + "group": null, + "hidden": true, + "interface": null, + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 2, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "tab_id", + "table": "tab_items", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": "tab", + "foreign_key_column": "id" + } +} diff --git a/backend/directus-config/development/snapshot/fields/tabs/icon_as_labels.json b/backend/directus-config/development/snapshot/fields/tabs/icon_as_labels.json new file mode 100644 index 00000000..12915289 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tabs/icon_as_labels.json @@ -0,0 +1,45 @@ +{ + "collection": "tabs", + "field": "icon_as_labels", + "type": "boolean", + "meta": { + "collection": "tabs", + "conditions": null, + "display": null, + "display_options": null, + "field": "icon_as_labels", + "group": null, + "hidden": false, + "interface": "boolean", + "note": "Show icons only when tab is not active", + "options": null, + "readonly": false, + "required": false, + "sort": 2, + "special": [ + "cast-boolean" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "icon_as_labels", + "table": "tabs", + "data_type": "boolean", + "default_value": false, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tabs/id.json b/backend/directus-config/development/snapshot/fields/tabs/id.json new file mode 100644 index 00000000..1fb0902f --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tabs/id.json @@ -0,0 +1,45 @@ +{ + "collection": "tabs", + "field": "id", + "type": "uuid", + "meta": { + "collection": "tabs", + "conditions": null, + "display": null, + "display_options": null, + "field": "id", + "group": null, + "hidden": true, + "interface": "input", + "note": null, + "options": null, + "readonly": true, + "required": false, + "sort": 1, + "special": [ + "uuid" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "id", + "table": "tabs", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": true, + "is_indexed": false, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tabs/tabs.json b/backend/directus-config/development/snapshot/fields/tabs/tabs.json new file mode 100644 index 00000000..96006f41 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tabs/tabs.json @@ -0,0 +1,33 @@ +{ + "collection": "tabs", + "field": "tabs", + "type": "alias", + "meta": { + "collection": "tabs", + "conditions": null, + "display": "related-values", + "display_options": { + "template": "{{title}}" + }, + "field": "tabs", + "group": null, + "hidden": false, + "interface": "list-o2m", + "note": "Individual tabs in this container", + "options": { + "enableCreate": true, + "enableSelect": false, + "template": "{{title}}" + }, + "readonly": false, + "required": false, + "sort": 4, + "special": [ + "o2m" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + } +} diff --git a/backend/directus-config/development/snapshot/fields/tags_component/dataField.json b/backend/directus-config/development/snapshot/fields/tags_component/dataField.json new file mode 100644 index 00000000..317b4e72 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tags_component/dataField.json @@ -0,0 +1,54 @@ +{ + "collection": "tags_component", + "field": "dataField", + "type": "string", + "meta": { + "collection": "tags_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "dataField", + "group": null, + "hidden": false, + "interface": "select-dropdown", + "note": "Which field to use: offers or needs", + "options": { + "choices": [ + { + "text": "Offers", + "value": "offers" + }, + { + "text": "Needs", + "value": "needs" + } + ] + }, + "readonly": false, + "required": true, + "sort": 2, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "dataField", + "table": "tags_component", + "data_type": "character varying", + "default_value": "offers", + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tags_component/heading.json b/backend/directus-config/development/snapshot/fields/tags_component/heading.json new file mode 100644 index 00000000..5cc57a36 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tags_component/heading.json @@ -0,0 +1,43 @@ +{ + "collection": "tags_component", + "field": "heading", + "type": "string", + "meta": { + "collection": "tags_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "heading", + "group": null, + "hidden": false, + "interface": "input", + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 3, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "heading", + "table": "tags_component", + "data_type": "character varying", + "default_value": null, + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tags_component/hideWhenEmpty.json b/backend/directus-config/development/snapshot/fields/tags_component/hideWhenEmpty.json new file mode 100644 index 00000000..ca95ac84 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tags_component/hideWhenEmpty.json @@ -0,0 +1,45 @@ +{ + "collection": "tags_component", + "field": "hideWhenEmpty", + "type": "boolean", + "meta": { + "collection": "tags_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "hideWhenEmpty", + "group": null, + "hidden": false, + "interface": "boolean", + "note": null, + "options": null, + "readonly": false, + "required": false, + "sort": 4, + "special": [ + "cast-boolean" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "half" + }, + "schema": { + "name": "hideWhenEmpty", + "table": "tags_component", + "data_type": "boolean", + "default_value": true, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tags_component/id.json b/backend/directus-config/development/snapshot/fields/tags_component/id.json new file mode 100644 index 00000000..527b2f7d --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tags_component/id.json @@ -0,0 +1,45 @@ +{ + "collection": "tags_component", + "field": "id", + "type": "uuid", + "meta": { + "collection": "tags_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "id", + "group": null, + "hidden": true, + "interface": "input", + "note": null, + "options": null, + "readonly": true, + "required": false, + "sort": 1, + "special": [ + "uuid" + ], + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "id", + "table": "tags_component", + "data_type": "uuid", + "default_value": null, + "max_length": null, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": false, + "is_unique": true, + "is_indexed": false, + "is_primary_key": true, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/fields/tags_component/placeholder.json b/backend/directus-config/development/snapshot/fields/tags_component/placeholder.json new file mode 100644 index 00000000..67b34f11 --- /dev/null +++ b/backend/directus-config/development/snapshot/fields/tags_component/placeholder.json @@ -0,0 +1,43 @@ +{ + "collection": "tags_component", + "field": "placeholder", + "type": "string", + "meta": { + "collection": "tags_component", + "conditions": null, + "display": null, + "display_options": null, + "field": "placeholder", + "group": null, + "hidden": false, + "interface": "input", + "note": "Placeholder text for the input field", + "options": null, + "readonly": false, + "required": false, + "sort": 5, + "special": null, + "translations": null, + "validation": null, + "validation_message": null, + "width": "full" + }, + "schema": { + "name": "placeholder", + "table": "tags_component", + "data_type": "character varying", + "default_value": null, + "max_length": 255, + "numeric_precision": null, + "numeric_scale": null, + "is_nullable": true, + "is_unique": false, + "is_indexed": false, + "is_primary_key": false, + "is_generated": false, + "generation_expression": null, + "has_auto_increment": false, + "foreign_key_table": null, + "foreign_key_column": null + } +} diff --git a/backend/directus-config/development/snapshot/relations/tab/tabs_id.json b/backend/directus-config/development/snapshot/relations/tab/tabs_id.json new file mode 100644 index 00000000..4f953c76 --- /dev/null +++ b/backend/directus-config/development/snapshot/relations/tab/tabs_id.json @@ -0,0 +1,25 @@ +{ + "collection": "tab", + "field": "tabs_id", + "related_collection": "tabs", + "meta": { + "junction_field": null, + "many_collection": "tab", + "many_field": "tabs_id", + "one_allowed_collections": null, + "one_collection": "tabs", + "one_collection_field": null, + "one_deselect_action": "nullify", + "one_field": "tabs", + "sort_field": "sort" + }, + "schema": { + "table": "tab", + "column": "tabs_id", + "foreign_key_table": "tabs", + "foreign_key_column": "id", + "constraint_name": "tab_tabs_id_foreign", + "on_update": "NO ACTION", + "on_delete": "SET NULL" + } +} diff --git a/backend/directus-config/development/snapshot/relations/tab_items/item.json b/backend/directus-config/development/snapshot/relations/tab_items/item.json new file mode 100644 index 00000000..534ff696 --- /dev/null +++ b/backend/directus-config/development/snapshot/relations/tab_items/item.json @@ -0,0 +1,27 @@ +{ + "collection": "tab_items", + "field": "item", + "related_collection": null, + "meta": { + "junction_field": "tab_id", + "many_collection": "tab_items", + "many_field": "item", + "one_allowed_collections": [ + "groupSubheaders", + "contactInfos", + "texts", + "startEnd", + "gallery", + "crowdfundings", + "inviteLinks", + "relations", + "tags_component", + "attestations_component" + ], + "one_collection": null, + "one_collection_field": "collection", + "one_deselect_action": "nullify", + "one_field": null, + "sort_field": null + } +} diff --git a/backend/directus-config/development/snapshot/relations/tab_items/tab_id.json b/backend/directus-config/development/snapshot/relations/tab_items/tab_id.json new file mode 100644 index 00000000..89a6033f --- /dev/null +++ b/backend/directus-config/development/snapshot/relations/tab_items/tab_id.json @@ -0,0 +1,25 @@ +{ + "collection": "tab_items", + "field": "tab_id", + "related_collection": "tab", + "meta": { + "junction_field": "item", + "many_collection": "tab_items", + "many_field": "tab_id", + "one_allowed_collections": null, + "one_collection": "tab", + "one_collection_field": null, + "one_deselect_action": "nullify", + "one_field": "items", + "sort_field": "sort" + }, + "schema": { + "table": "tab_items", + "column": "tab_id", + "foreign_key_table": "tab", + "foreign_key_column": "id", + "constraint_name": "tab_items_tab_id_foreign", + "on_update": "NO ACTION", + "on_delete": "SET NULL" + } +} diff --git a/backend/directus-config/development/snapshot/relations/types_profileTemplate/item.json b/backend/directus-config/development/snapshot/relations/types_profileTemplate/item.json index 2029ab84..39598ff8 100644 --- a/backend/directus-config/development/snapshot/relations/types_profileTemplate/item.json +++ b/backend/directus-config/development/snapshot/relations/types_profileTemplate/item.json @@ -14,7 +14,10 @@ "gallery", "crowdfundings", "inviteLinks", - "relations" + "relations", + "tags_component", + "attestations_component", + "tabs" ], "one_collection": null, "one_collection_field": "collection", diff --git a/lib/src/Components/Input/Autocomplete.tsx b/lib/src/Components/Input/Autocomplete.tsx index 2bb97d2c..12dd76cb 100644 --- a/lib/src/Components/Input/Autocomplete.tsx +++ b/lib/src/Components/Input/Autocomplete.tsx @@ -66,6 +66,7 @@ export const Autocomplete = ({ heighlightedSuggestion > 0 && setHeighlightedSuggestion((current) => current - 1) break case 'Enter': + event.preventDefault() if (filteredSuggestions.length > 0) { // eslint-disable-next-line security/detect-object-injection onSelected(filteredSuggestions[heighlightedSuggestion]) @@ -80,7 +81,7 @@ export const Autocomplete = ({ } return ( -
+
handleChange(e)} tabIndex='-1' onKeyDown={handleKeyDown} - className='tw:border-none tw:focus:outline-none tw:focus:ring-0 tw:mt-5' + className='tw:border-none tw:focus:outline-none tw:focus:ring-0 tw:mt-5 tw:w-full' />
    0 && 'tw:bg-base-100 tw:rounded-xl tw:p-2'}`} diff --git a/lib/src/Components/Profile/ProfileView.tsx b/lib/src/Components/Profile/ProfileView.tsx index fba3319c..ede4d057 100644 --- a/lib/src/Components/Profile/ProfileView.tsx +++ b/lib/src/Components/Profile/ProfileView.tsx @@ -22,6 +22,7 @@ import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/He import { MapOverlayPage } from '#components/Templates' import { handleDelete, linkItem, unlinkItem } from './itemFunctions' +import { AttestationsContext } from './hooks/useAttestations' import { FlexView } from './Templates/FlexView' import { OnepagerView } from './Templates/OnepagerView' import { SimpleView } from './Templates/SimpleView' @@ -201,7 +202,11 @@ export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi {template === 'simple' && } - {template === 'flex' && } + {template === 'flex' && ( + + + + )} {template === 'tabs' && ( { + const attestations = useAttestations() + const items = useItems() + const appState = useAppState() + + const getUserProfile = (userId: string) => { + return items.find((i) => i.user_created?.id === userId && i.layer?.userProfileLayer) + } + + // Filter attestations for this user + const userAttestations = attestations + .filter((a) => a.to.some((t) => t.directus_users_id === item.user_created?.id)) + .sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime()) + + if (hideWhenEmpty && userAttestations.length === 0) { + return null + } + + return ( +
    +

    {heading}

    + + + {userAttestations.map((a, i) => ( + + + + + + ))} + +
    +
    + {a.emoji} +
    +
    +
    + {a.text} +
    +
    + {getUserProfile(a.user_created.id) ? ( + +
    +
    +
    + {getUserProfile(a.user_created.id)?.image && ( + Avatar + )} +
    +
    +
    +
    + {getUserProfile(a.user_created.id)?.name ?? a.user_created.first_name}{' '} +
    +
    + {timeAgo(a.date_created)} +
    +
    +
    + + ) : ( +
    +
    {a.user_created.first_name}
    +
    + {timeAgo(a.date_created)} +
    +
    + )} +
    +
    + ) +} diff --git a/lib/src/Components/Profile/Subcomponents/ContactInfoView.tsx b/lib/src/Components/Profile/Subcomponents/ContactInfoView.tsx index e0595f48..789efaf5 100644 --- a/lib/src/Components/Profile/Subcomponents/ContactInfoView.tsx +++ b/lib/src/Components/Profile/Subcomponents/ContactInfoView.tsx @@ -24,7 +24,7 @@ export const ContactInfoView = ({ item, heading }: { item: Item; heading: string }, [item, items]) return ( -
    +

    {heading}

    {profileOwner?.image && ( diff --git a/lib/src/Components/Profile/Subcomponents/CrowdfundingView.tsx b/lib/src/Components/Profile/Subcomponents/CrowdfundingView.tsx index 3ea27f62..6249fae8 100644 --- a/lib/src/Components/Profile/Subcomponents/CrowdfundingView.tsx +++ b/lib/src/Components/Profile/Subcomponents/CrowdfundingView.tsx @@ -144,7 +144,7 @@ export const CrowdfundingView = ({ item }: { item: Item }) => { const currentBalance = balanceValueInCents return ( -
    +
    diff --git a/lib/src/Components/Profile/Subcomponents/GalleryView.tsx b/lib/src/Components/Profile/Subcomponents/GalleryView.tsx index 4d8b7094..cac15f4a 100644 --- a/lib/src/Components/Profile/Subcomponents/GalleryView.tsx +++ b/lib/src/Components/Profile/Subcomponents/GalleryView.tsx @@ -40,7 +40,7 @@ export const GalleryView = ({ item }: { item: Item }) => { if (images.length > 0) return ( -
    +
    ( -
    +
    {item.status && (
    diff --git a/lib/src/Components/Profile/Subcomponents/InviteLinkView.tsx b/lib/src/Components/Profile/Subcomponents/InviteLinkView.tsx index 34bf615b..42715159 100644 --- a/lib/src/Components/Profile/Subcomponents/InviteLinkView.tsx +++ b/lib/src/Components/Profile/Subcomponents/InviteLinkView.tsx @@ -17,7 +17,7 @@ export const InviteLinkView = ({ item }: { item: Item }) => { } return ( -
    +

    Invite

    { return ( -
    +
    ) diff --git a/lib/src/Components/Profile/Subcomponents/ProfileTagsForm.tsx b/lib/src/Components/Profile/Subcomponents/ProfileTagsForm.tsx new file mode 100644 index 00000000..61612704 --- /dev/null +++ b/lib/src/Components/Profile/Subcomponents/ProfileTagsForm.tsx @@ -0,0 +1,41 @@ +import { TagsWidget } from '#components/Profile/Subcomponents/TagsWidget' + +import type { FormState } from '#types/FormState' +import type { Item } from '#types/Item' + +interface Props { + item: Item + state: FormState + setState: React.Dispatch> + dataField: 'offers' | 'needs' + heading?: string + placeholder?: string +} + +export const ProfileTagsForm = ({ + state, + setState, + dataField, + heading, + placeholder, +}: Props) => { + const defaultHeading = dataField === 'offers' ? 'Offers' : 'Needs' + const defaultPlaceholder = dataField === 'offers' ? 'enter your offers' : 'enter your needs' + + return ( +
    +

    {heading ?? defaultHeading}

    + + setState((prevState) => ({ + ...prevState, + [dataField]: tags, + })) + } + placeholder={placeholder ?? defaultPlaceholder} + containerStyle='tw:bg-transparent tw:w-full tw:flex-1 tw:text-xs tw:pb-2 tw:overflow-auto' + /> +
    + ) +} diff --git a/lib/src/Components/Profile/Subcomponents/ProfileTagsView.tsx b/lib/src/Components/Profile/Subcomponents/ProfileTagsView.tsx new file mode 100644 index 00000000..dcc016f0 --- /dev/null +++ b/lib/src/Components/Profile/Subcomponents/ProfileTagsView.tsx @@ -0,0 +1,56 @@ +import { useAddFilterTag } from '#components/Map/hooks/useFilter' +import { useTags } from '#components/Map/hooks/useTags' +import { TagView } from '#components/Templates/TagView' + +import type { Item } from '#types/Item' +import type { Tag } from '#types/Tag' + +interface Props { + item: Item + dataField: 'offers' | 'needs' + heading?: string + hideWhenEmpty?: boolean +} + +export const ProfileTagsView = ({ + item, + dataField, + heading, + hideWhenEmpty = true, +}: Props) => { + const addFilterTag = useAddFilterTag() + const allTags = useTags() + + // Get the tag IDs from the item based on dataField + const tagRelations = item[dataField] ?? [] + + // Resolve tag IDs to full Tag objects + const tags: Tag[] = tagRelations.reduce((acc: Tag[], relation) => { + const tag = allTags.find((t) => t.id === relation.tags_id) + if (tag) acc.push(tag) + return acc + }, []) + + if (hideWhenEmpty && tags.length === 0) { + return null + } + + const defaultHeading = dataField === 'offers' ? 'Offers' : 'Needs' + + return ( +
    +

    {heading ?? defaultHeading}

    +
    + {tags.map((tag) => ( + { + addFilterTag(tag) + }} + /> + ))} +
    +
    + ) +} diff --git a/lib/src/Components/Profile/Subcomponents/ProfileTextView.tsx b/lib/src/Components/Profile/Subcomponents/ProfileTextView.tsx index ea62c6d7..1b1e4456 100644 --- a/lib/src/Components/Profile/Subcomponents/ProfileTextView.tsx +++ b/lib/src/Components/Profile/Subcomponents/ProfileTextView.tsx @@ -21,7 +21,7 @@ export const ProfileTextView = ({ const shouldShowHeading = !(hideWhenEmpty && (text === '' || text === null)) return ( -
    +
    {shouldShowHeading &&

    {heading}

    }
    diff --git a/lib/src/Components/Profile/Subcomponents/RelationsView.tsx b/lib/src/Components/Profile/Subcomponents/RelationsView.tsx index a1fc1f02..fcdadf9b 100644 --- a/lib/src/Components/Profile/Subcomponents/RelationsView.tsx +++ b/lib/src/Components/Profile/Subcomponents/RelationsView.tsx @@ -60,7 +60,7 @@ export const RelationsView = ({ } return ( -
    +

    {heading}

    {hasRelatedItems ? (
      diff --git a/lib/src/Components/Profile/Subcomponents/TabsContainerForm.tsx b/lib/src/Components/Profile/Subcomponents/TabsContainerForm.tsx new file mode 100644 index 00000000..e3b3eb54 --- /dev/null +++ b/lib/src/Components/Profile/Subcomponents/TabsContainerForm.tsx @@ -0,0 +1,133 @@ +import { useCallback, useEffect, useState } from 'react' +import { useLocation, useNavigate } from 'react-router-dom' + +import { ContactInfoForm } from '#components/Profile/Subcomponents/ContactInfoForm' +import { CrowdfundingForm } from '#components/Profile/Subcomponents/CrowdfundingForm' +import { GalleryForm } from '#components/Profile/Subcomponents/GalleryForm' +import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm' +import { ProfileStartEndForm } from '#components/Profile/Subcomponents/ProfileStartEndForm' +import { ProfileTextForm } from '#components/Profile/Subcomponents/ProfileTextForm' +import { ProfileTagsForm } from '#components/Profile/Subcomponents/ProfileTagsForm' + +import type { FormState } from '#types/FormState' +import type { Item } from '#types/Item' +import type { Key } from 'react' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ComponentMap = Record> + +const componentMap: ComponentMap = { + groupSubheaders: GroupSubheaderForm, + texts: ProfileTextForm, + contactInfos: ContactInfoForm, + startEnd: ProfileStartEndForm, + crowdfundings: CrowdfundingForm, + gallery: GalleryForm, + inviteLinks: () => null, + relations: () => null, // Relations are not editable in form + tags_component: ProfileTagsForm, + attestations_component: () => null, // Attestations are view-only +} + +interface TabItem { + id: string + title: string + icon?: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any + items: Array<{ collection: string; id: Key | null | undefined; item: any }> +} + +interface Props { + item: Item + state: FormState + setState: React.Dispatch> + tabs: TabItem[] + icon_as_labels?: boolean +} + +export const TabsContainerForm = ({ + item, + state, + setState, + tabs, + icon_as_labels = false, +}: Props) => { + const location = useLocation() + const navigate = useNavigate() + const [activeTab, setActiveTab] = useState(0) + + const tabsLength = tabs?.length ?? 0 + + useEffect(() => { + if (!tabs || tabs.length === 0) return + + const params = new URLSearchParams(location.search) + const urlTab = params.get('tab') + if (urlTab !== null && !isNaN(Number(urlTab))) { + const index = Number(urlTab) + if (index >= 0 && index < tabs.length) { + setActiveTab(index) + } + } + }, [tabs, tabsLength, location.search]) + + const updateActiveTab = useCallback( + (index: number) => { + setActiveTab(index) + const params = new URLSearchParams(location.search) + params.set('tab', `${index}`) + const newUrl = location.pathname + '?' + params.toString() + navigate(newUrl, { replace: false }) + }, + [location.pathname, location.search, navigate], + ) + + if (!tabs || tabs.length === 0) { + return null + } + + return ( +
      + {/* Tabs */} +
      + {tabs.map((tab, index) => ( + + ))} +
      + + {/* Tab Content */} +
      + {tabs[activeTab]?.items.map((templateItem) => { + const TemplateComponent = componentMap[templateItem.collection] + return TemplateComponent ? ( + + ) : ( +
      + {templateItem.collection} form not found +
      + ) + })} +
      +
      + ) +} diff --git a/lib/src/Components/Profile/Subcomponents/TabsContainerView.tsx b/lib/src/Components/Profile/Subcomponents/TabsContainerView.tsx new file mode 100644 index 00000000..36121044 --- /dev/null +++ b/lib/src/Components/Profile/Subcomponents/TabsContainerView.tsx @@ -0,0 +1,115 @@ +/* eslint-disable camelcase */ +import React, { useCallback, useEffect, useState } from 'react' +import { useLocation, useNavigate } from 'react-router-dom' + +import { AttestationsView } from '#components/Profile/Subcomponents/AttestationsView' +import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoView' +import { CrowdfundingView } from '#components/Profile/Subcomponents/CrowdfundingView' +import { GalleryView } from '#components/Profile/Subcomponents/GalleryView' +import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView' +import { InviteLinkView } from '#components/Profile/Subcomponents/InviteLinkView' +import { ProfileStartEndView } from '#components/Profile/Subcomponents/ProfileStartEndView' +import { ProfileTagsView } from '#components/Profile/Subcomponents/ProfileTagsView' +import { ProfileTextView } from '#components/Profile/Subcomponents/ProfileTextView' +import { RelationsView } from '#components/Profile/Subcomponents/RelationsView' + +import type { Item } from '#types/Item' +import type { Key } from 'react' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ComponentMap = Record> + +const componentMap: ComponentMap = { + groupSubheaders: GroupSubHeaderView, + texts: ProfileTextView, + contactInfos: ContactInfoView, + startEnd: ProfileStartEndView, + gallery: GalleryView, + crowdfundings: CrowdfundingView, + inviteLinks: InviteLinkView, + relations: RelationsView, + tags_component: ProfileTagsView, + attestations_component: AttestationsView, +} + +interface TabItem { + id: string + title: string + icon?: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any + items: { collection: string; id: Key | null | undefined; item: any }[] +} + +interface Props { + item: Item + tabs: TabItem[] + icon_as_labels?: boolean +} + +export const TabsContainerView = ({ item, tabs = [], icon_as_labels = false }: Props) => { + const location = useLocation() + const navigate = useNavigate() + const [activeTab, setActiveTab] = useState(0) + + const tabsLength = tabs.length + + useEffect(() => { + if (tabs.length === 0) return + + const params = new URLSearchParams(location.search) + const urlTab = params.get('tab') + if (urlTab !== null && !isNaN(Number(urlTab))) { + const index = Number(urlTab) + if (index >= 0 && index < tabs.length) { + setActiveTab(index) + } + } + }, [tabs, tabsLength, location.search]) + + const updateActiveTab = useCallback( + (index: number) => { + setActiveTab(index) + const params = new URLSearchParams(location.search) + params.set('tab', `${index}`) + const newUrl = location.pathname + '?' + params.toString() + navigate(newUrl, { replace: false }) + }, + [location.pathname, location.search, navigate], + ) + + if (tabs.length === 0) { + return null + } + + return ( +
      + {/* Tabs */} +
      + {tabs.map((tab, index) => ( + + ))} +
      + + {/* Tab Content */} +
      + {tabs[activeTab]?.items.map((templateItem) => { + const TemplateComponent = componentMap[templateItem.collection] + return TemplateComponent ? ( + + ) : ( +
      + {templateItem.collection} view not found +
      + ) + })} +
      +
      + ) +} diff --git a/lib/src/Components/Profile/Subcomponents/TagsWidget.tsx b/lib/src/Components/Profile/Subcomponents/TagsWidget.tsx index 193a6cbb..5eee1e97 100644 --- a/lib/src/Components/Profile/Subcomponents/TagsWidget.tsx +++ b/lib/src/Components/Profile/Subcomponents/TagsWidget.tsx @@ -97,7 +97,7 @@ export const TagsWidget = ({ placeholder, containerStyle, defaultTags, onUpdate onKeyDown, onKeyUp, onChange, - className: 'tw:bg-transparent tw:w-fit tw:mt-5 tw:h-fit', + className: 'tw:bg-transparent tw:min-w-48 tw:w-fit tw:mt-5 tw:h-fit', } /* eslint-disable react/prop-types */ diff --git a/lib/src/Components/Profile/Templates/FlexForm.tsx b/lib/src/Components/Profile/Templates/FlexForm.tsx index 59406070..02b3d127 100644 --- a/lib/src/Components/Profile/Templates/FlexForm.tsx +++ b/lib/src/Components/Profile/Templates/FlexForm.tsx @@ -5,7 +5,9 @@ import { CrowdfundingForm } from '#components/Profile/Subcomponents/Crowdfunding import { GalleryForm } from '#components/Profile/Subcomponents/GalleryForm' import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm' import { ProfileStartEndForm } from '#components/Profile/Subcomponents/ProfileStartEndForm' +import { ProfileTagsForm } from '#components/Profile/Subcomponents/ProfileTagsForm' import { ProfileTextForm } from '#components/Profile/Subcomponents/ProfileTextForm' +import { TabsContainerForm } from '#components/Profile/Subcomponents/TabsContainerForm' import type { FormState } from '#types/FormState' import type { Item } from '#types/Item' @@ -17,8 +19,11 @@ const componentMap = { startEnd: ProfileStartEndForm, crowdfundings: CrowdfundingForm, gallery: GalleryForm, - inviteLinks: () => null, // Not needed for now - // weitere Komponenten hier + inviteLinks: () => null, + relations: () => null, + tags_component: ProfileTagsForm, + attestations_component: () => null, + tabs: TabsContainerForm, } export const FlexForm = ({ diff --git a/lib/src/Components/Profile/Templates/FlexView.tsx b/lib/src/Components/Profile/Templates/FlexView.tsx index e3024c45..2ff41d1b 100644 --- a/lib/src/Components/Profile/Templates/FlexView.tsx +++ b/lib/src/Components/Profile/Templates/FlexView.tsx @@ -1,13 +1,16 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import { AttestationsView } from '#components/Profile/Subcomponents/AttestationsView' import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoView' import { CrowdfundingView } from '#components/Profile/Subcomponents/CrowdfundingView' import { GalleryView } from '#components/Profile/Subcomponents/GalleryView' import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView' import { InviteLinkView } from '#components/Profile/Subcomponents/InviteLinkView' import { ProfileStartEndView } from '#components/Profile/Subcomponents/ProfileStartEndView' +import { ProfileTagsView } from '#components/Profile/Subcomponents/ProfileTagsView' import { ProfileTextView } from '#components/Profile/Subcomponents/ProfileTextView' import { RelationsView } from '#components/Profile/Subcomponents/RelationsView' +import { TabsContainerView } from '#components/Profile/Subcomponents/TabsContainerView' import type { Item } from '#types/Item' import type { Key } from 'react' @@ -21,12 +24,14 @@ const componentMap = { crowdfundings: CrowdfundingView, inviteLinks: InviteLinkView, relations: RelationsView, - // weitere Komponenten hier + tags_component: ProfileTagsView, + attestations_component: AttestationsView, + tabs: TabsContainerView, } export const FlexView = ({ item }: { item: Item }) => { return ( -
      +
      {item.layer?.itemType.profileTemplate.map( // eslint-disable-next-line @typescript-eslint/no-explicit-any (templateItem: { collection: string | number; id: Key | null | undefined; item: any }) => { diff --git a/lib/src/Components/Profile/hooks/useAttestations.ts b/lib/src/Components/Profile/hooks/useAttestations.ts new file mode 100644 index 00000000..1d23ad95 --- /dev/null +++ b/lib/src/Components/Profile/hooks/useAttestations.ts @@ -0,0 +1,16 @@ +import { createContext, useContext } from 'react' + +export interface Attestation { + id: string + text: string + emoji: string + color: string + shape: string + date_created: string + user_created: { id: string; first_name: string } + to: Array<{ directus_users_id: string }> +} + +export const AttestationsContext = createContext([]) + +export const useAttestations = () => useContext(AttestationsContext) diff --git a/package-lock.json b/package-lock.json index 0d8c462f..d70acbe7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -226,7 +226,6 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2422,7 +2421,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" @@ -3544,7 +3542,6 @@ "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4007,7 +4004,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.11.0.tgz", "integrity": "sha512-kmS7ZVpHm1EMnW1Wmft9H5ZLM7E0G0NGBx+aGEHGDcNxZBXD2ZUa76CuWjIhOGpwsPbELp684ZdpF2JWoNi4Dg==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4255,7 +4251,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.11.0.tgz", "integrity": "sha512-4Ane7VCVZ+GFOQNuy2nMP+SoWH7EemC3geTTqvgHm1H0tbSosxLJAVaZ9dF06F35RJmYCm+jLJUhRVd156eCRQ==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4401,7 +4396,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.11.0.tgz", "integrity": "sha512-g43beA73ZMLezez1st9LEwYrRHZ0FLzlsSlOZKk7sdmtHLmuqWHf4oyb0XAHol1HZIdGv104rYaGNgmQXr1ecQ==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4416,7 +4410,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.11.0.tgz", "integrity": "sha512-plCQDLCZIOc92cizB8NNhBRN0szvYR3cx9i5IXo6v9Xsgcun8KHNcJkesc2AyeqdIs0BtOJZaqQ9adHThz8UDw==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", @@ -4531,7 +4524,8 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -4539,7 +4533,6 @@ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -4663,7 +4656,6 @@ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", "license": "MIT", - "peer": true, "dependencies": { "@types/geojson": "*" } @@ -4743,7 +4735,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz", "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4754,7 +4745,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -4881,7 +4871,6 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -5498,7 +5487,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "devOptional": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6158,7 +6146,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -7247,7 +7234,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dom-serializer": { "version": "1.4.1", @@ -7426,7 +7414,6 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -7957,7 +7944,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -8039,7 +8025,6 @@ "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", @@ -8121,7 +8106,6 @@ "integrity": "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0" }, @@ -10549,8 +10533,7 @@ "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/leaflet.locatecontrol": { "version": "0.79.0", @@ -11113,6 +11096,7 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -11159,7 +11143,6 @@ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.9.0.tgz", "integrity": "sha512-YxW9glb/YrDXGDhqy1u+aG113+L86ttAUpTd6sCkGHyUKMXOX8qbGHJQVqxOczy+4CtRKnqcCfSura2MzB0nQA==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", @@ -12628,7 +12611,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -13264,7 +13246,6 @@ "integrity": "sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -13307,6 +13288,7 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -13322,6 +13304,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -13488,7 +13471,6 @@ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.3.tgz", "integrity": "sha512-dY2HdaNXlARknJbrManZ1WyUtos+AP97AmvqdOQtWtrrC5g4mohVX5DTi9rXNFSk09eczLq9GuNTtq3EfMeMGA==", "license": "MIT", - "peer": true, "dependencies": { "orderedmap": "^2.0.0" } @@ -13518,7 +13500,6 @@ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-transform": "^1.0.0", @@ -13567,7 +13548,6 @@ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.3.tgz", "integrity": "sha512-SqMiYMUQNNBP9kfPhLO8WXEk/fon47vc52FQsUiJzTBuyjKgEcoAwMyF04eQ4WZ2ArMn7+ReypYL60aKngbACQ==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -13699,7 +13679,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -13722,7 +13701,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -13806,14 +13784,14 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-leaflet": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", "license": "Hippocratic-2.1", - "peer": true, "dependencies": { "@react-leaflet/core": "^2.1.0" }, @@ -13947,7 +13925,6 @@ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", "license": "MIT", - "peer": true, "dependencies": { "@remix-run/router": "1.23.0", "react-router": "6.30.1" @@ -14271,7 +14248,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -15953,7 +15929,6 @@ "integrity": "sha512-/z585740YHURLl9DN2jCWe6OW7zKYm6VoQ93H0sxZ1cwHQEQrUn5BJrEnkWhfzUdyO+BLGjnKUZ9iz9hKloFDw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@gerrit0/mini-shiki": "^1.24.0", "lunr": "^2.3.9", @@ -16026,7 +16001,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16228,7 +16202,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -16407,7 +16380,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -16584,7 +16556,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -17061,7 +17032,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -17116,7 +17086,6 @@ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -17412,7 +17381,6 @@ "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }