From a0d0b5c4a4457ad0f152ff5f47cdbd2deb7d5436 Mon Sep 17 00:00:00 2001 From: duckietm Date: Mon, 23 Mar 2026 11:49:05 +0100 Subject: [PATCH] Revert "Merge branch 'main' into furnisettingeditor-pr" This reverts commit dfbfb1c2c1e91ec236d863272d457a82a466176b, reversing changes made to 07702c44d09cd59d7b8200ae3c7e3ec19dce54f3. --- .gitignore | 2 - CatalogTexts.json | 68 - catalog_favorites.sql | 7 - public/UITexts.example | 21 +- public/renderer-config.json | 586 --- public/ui-config.json | 1121 +++++- .../avatar/AvatarEditorThumbnailsHelper.ts | 6 +- src/api/wired/WiredActionLayoutCode.ts | 4 - .../AvatarEditorFigureSetItemView.tsx | 2 +- .../catalog/CatalogAdminContext.tsx | 296 -- src/components/catalog/CatalogClassicView.tsx | 183 - src/components/catalog/CatalogModernView.tsx | 291 -- src/components/catalog/CatalogView.tsx | 117 +- .../views/admin/CatalogAdminOfferEditView.tsx | 225 -- .../views/admin/CatalogAdminPageEditView.tsx | 153 - .../catalog-rail/CatalogRailItemView.tsx | 30 - .../views/favorites/CatalogFavoritesView.tsx | 154 - .../navigation/CatalogBreadcrumbView.tsx | 39 - .../navigation/CatalogNavigationItemView.tsx | 132 +- .../navigation/CatalogNavigationView.tsx | 23 +- .../page/common/CatalogGridOfferView.tsx | 26 +- .../views/page/common/CatalogSearchView.tsx | 43 +- .../layout/CatalogLayoutCustomPrefixView.tsx | 85 +- .../page/layout/CatalogLayoutDefaultView.tsx | 125 +- .../page/layout/CatalogLayoutPets3View.tsx | 33 +- .../page/layout/CatalogLayoutTrophiesView.tsx | 128 +- .../page/layout/pets/CatalogLayoutPetView.tsx | 177 +- .../widgets/CatalogItemGridWidgetView.tsx | 66 +- .../widgets/CatalogPriceDisplayWidgetView.tsx | 14 +- .../page/widgets/CatalogSpinnerWidgetView.tsx | 34 +- .../furni-editor/FurniEditorView.tsx | 17 - .../views/FurniEditorCreateView.tsx | 21 - .../views/FurniEditorEditView.tsx | 30 - .../actions/WiredActionFurniToFurniView.tsx | 21 +- .../views/actions/WiredActionLayoutView.tsx | 12 - .../actions/WiredActionSendSignalView.tsx | 37 +- .../WiredConditionFurniIsOfTypeView.tsx | 21 +- .../extras/WiredExtraAnimationTimeView.tsx | 47 - .../extras/WiredExtraMoveCarryUsersView.tsx | 62 - .../extras/WiredExtraMoveNoAnimationView.tsx | 25 - .../extras/WiredExtraMovePhysicsView.tsx | 120 - .../WiredSelectorFurniByTypeView.tsx | 7 +- src/css/index.css | 45 +- src/hooks/catalog/index.ts | 1 - src/hooks/catalog/useCatalogFavorites.ts | 129 - src/hooks/furni-editor/useFurniEditor.ts | 12 - src/hooks/wired/useWired.ts | 5 +- tailwind.config.js | 18 +- vite.config.mjs | 14 +- yarn.lock | 3238 +++++++++++++++++ 50 files changed, 4746 insertions(+), 3327 deletions(-) delete mode 100644 CatalogTexts.json delete mode 100644 catalog_favorites.sql delete mode 100644 src/components/catalog/CatalogAdminContext.tsx delete mode 100644 src/components/catalog/CatalogClassicView.tsx delete mode 100644 src/components/catalog/CatalogModernView.tsx delete mode 100644 src/components/catalog/views/admin/CatalogAdminOfferEditView.tsx delete mode 100644 src/components/catalog/views/admin/CatalogAdminPageEditView.tsx delete mode 100644 src/components/catalog/views/catalog-rail/CatalogRailItemView.tsx delete mode 100644 src/components/catalog/views/favorites/CatalogFavoritesView.tsx delete mode 100644 src/components/catalog/views/navigation/CatalogBreadcrumbView.tsx delete mode 100644 src/components/wired/views/extras/WiredExtraAnimationTimeView.tsx delete mode 100644 src/components/wired/views/extras/WiredExtraMoveCarryUsersView.tsx delete mode 100644 src/components/wired/views/extras/WiredExtraMoveNoAnimationView.tsx delete mode 100644 src/components/wired/views/extras/WiredExtraMovePhysicsView.tsx delete mode 100644 src/hooks/catalog/useCatalogFavorites.ts create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index 506f80d..249e7db 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,3 @@ Thumbs.db *.zip .env .claude/ -public/renderer-config.json -public/ui-config.json diff --git a/CatalogTexts.json b/CatalogTexts.json deleted file mode 100644 index 7dbe65f..0000000 --- a/CatalogTexts.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "catalog.title": "Catalog", - "catalog.favorites": "Favorites", - "catalog.favorites.pages": "Pages", - "catalog.favorites.furni": "Furni", - "catalog.favorites.empty": "No favorites", - "catalog.favorites.empty.hint": "Click the heart on furni or the star on pages to add them.", - "catalog.admin": "Admin", - "catalog.admin.new": "New", - "catalog.admin.root": "Root", - "catalog.admin.new.root.category": "New root category", - "catalog.admin.edit.root": "Edit Root", - "catalog.admin.edit": "Edit:", - "catalog.admin.edit.page": "Edit Page", - "catalog.admin.hidden": "hidden", - "catalog.admin.edit.title": "Edit \"%name%\"", - "catalog.admin.show": "Show", - "catalog.admin.hide": "Hide", - "catalog.admin.delete": "Delete", - "catalog.admin.delete.title": "Delete \"%name%\"", - "catalog.admin.delete.category.confirm": "Delete category \"%name%\" and all its content?", - "catalog.admin.delete.page": "Delete page", - "catalog.admin.delete.page.confirm": "Delete page \"%name%\"?", - "catalog.admin.delete.offer.confirm": "Are you sure you want to delete this offer?", - "catalog.admin.create": "Create", - "catalog.admin.save": "Save", - "catalog.admin.create.subpage": "Create sub-page", - "catalog.admin.order": "Order", - "catalog.admin.visible": "Visible", - "catalog.admin.enabled": "Enabled", - "catalog.admin.offer.new": "New Offer", - "catalog.admin.offer.edit": "Edit Offer", - "catalog.admin.offer.name": "Catalog Name", - "catalog.admin.offer.general": "General", - "catalog.admin.offer.quantity": "Quantity", - "catalog.admin.offer.prices": "Prices", - "catalog.admin.offer.credits": "Credits", - "catalog.admin.offer.points": "Points", - "catalog.admin.offer.points.type": "Points Type", - "catalog.admin.offer.options": "Options", - "catalog.admin.offer.club.only": "Club Only", - "catalog.admin.offer.extradata": "Extra Data", - "catalog.admin.offer.have.offer": "Multi-discount (have_offer)", - "catalog.trophies.title": "Trophies", - "catalog.trophies.write.hint": "Write a text for the trophy before purchasing", - "catalog.trophies.inscription": "Trophy Inscription", - "catalog.trophies.inscription.placeholder": "Write the text that will appear on the trophy...", - "catalog.pets.show.colors": "Show colors", - "catalog.pets.choose.color": "Choose color", - "catalog.pets.choose.breed": "Choose breed", - "catalog.pets.back.breeds": "โ† Breeds", - "catalog.prefix.text": "Text", - "catalog.prefix.text.placeholder": "Enter text...", - "catalog.prefix.icon": "Icon", - "catalog.prefix.icon.remove": "Remove icon", - "catalog.prefix.effect": "Effect", - "catalog.prefix.color": "Color", - "catalog.prefix.color.single": "๐ŸŽจ Single", - "catalog.prefix.color.per.letter": "๐ŸŒˆ Per Letter", - "catalog.prefix.color.hint": "Select a letter, then choose the color. Auto-advances.", - "catalog.prefix.color.apply.all.title": "Apply current color to all letters", - "catalog.prefix.color.apply.all": "Apply to all", - "catalog.prefix.color.selected": "Selected letter:", - "catalog.prefix.price": "Price:", - "catalog.prefix.price.amount": "5 Credits", - "catalog.prefix.purchased": "โœ“ Purchased!", - "catalog.prefix.purchase": "Purchase" -} diff --git a/catalog_favorites.sql b/catalog_favorites.sql deleted file mode 100644 index c178581..0000000 --- a/catalog_favorites.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE IF NOT EXISTS catalog_favorites ( - user_id INT NOT NULL, - type ENUM('offer', 'page') NOT NULL, - target_id INT NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (user_id, type, target_id) -); diff --git a/public/UITexts.example b/public/UITexts.example index 539f71a..fe20439 100644 --- a/public/UITexts.example +++ b/public/UITexts.example @@ -20,24 +20,5 @@ "widget.room.chat.clear_history": "leeg geschiedenis", "widget.room.youtube.shared": "YouTube word gedeeld", "widget.room.youtube.open_video": "Open de video", - "wiredfurni.params.area_selection.selected": "Geselecteerd gebied: Lengte=%x%, Breedte=%y%, breedte=%w%, hoogte=%h%", - "wiredfurni.params.carry_mode": "Gli utenti sono trasportati quando:", - "wiredfurni.params.carry_mode.0": "rimani fermo direttamente sul Furni in movimento", - "wiredfurni.params.carry_mode.1": "rimani fermo sulla stessa casella del Furni in movimento", - "wiredfurni.params.sources.users.title.carry": "Consentire il trasporto per:", - "wiredfurni.params.sources.users.900": "Tutti gli utenti nella Stanza", - "wiredfurni.params.anim_time.title": "Durata animazione movimento", - "wiredfurni.params.anim_time.description": "Regola la velocita dello slide per i Wired che spostano utenti e furni.", - "wiredfurni.params.anim_time.value": "%ms% ms", - "wiredfurni.params.mov_no_animation.title": "Animazione movimento", - "wiredfurni.params.mov_no_animation.description": "Questo extra disattiva lo slide per i Wired che spostano utenti e furni.", - "wiredfurni.params.select_options": "Seleziona opzioni:", - "wiredfurni.params.movephysics.keep_altitude": "Mantieni altitudine del Furni", - "wiredfurni.params.movephysics.move_through_furni": "Muovi attraverso Furni", - "wiredfurni.params.movephysics.move_through_users": "Muovi attraverso utenti", - "wiredfurni.params.movephysics.block_by_furni": "รจ bloccato da Furni", - "wiredfurni.params.sources.furni.title.physics.0": "Muovi attraverso Furni:", - "wiredfurni.params.sources.furni.title.physics.1": "Bloccato da Furni:", - "wiredfurni.params.sources.users.title.physics.0": "Muovi attraverso gli utenti:", - "wiredfurni.params.sources.furni.900": "Tutti i Furni nella Stanza" + "wiredfurni.params.area_selection.selected": "Geselecteerd gebied: Lengte=%x%, Breedte=%y%, breedte=%w%, hoogte=%h%" } diff --git a/public/renderer-config.json b/public/renderer-config.json index 7322252..1c2b22a 100644 --- a/public/renderer-config.json +++ b/public/renderer-config.json @@ -107,590 +107,4 @@ "${images.url}/clear_icon.png", "${images.url}/big_arrow.png" ] -} - "socket.url": "ws://192.168.1.52:2096", - "asset.url": "https://client.paxxo.online/nitro/bundled", - "image.library.url": "https://client.paxxo.online/c_images/", - "hof.furni.url": "https://client.paxxo.online/c_images/dcr/hof_furni", - "images.url": "https://client.paxxo.online/nitro/images", - "gamedata.url": "https://client.paxxo.online/nitro/gamedata", - "sounds.url": "${asset.url}/sounds/%sample%.mp3", - "external.texts.url": [ - "${gamedata.url}/ExternalTexts.json", - "${gamedata.url}/UITexts.json" - ], - "external.samples.url": "${hof.furni.url}/mp3/sound_machine_sample_%sample%.mp3", - "furnidata.url": "${gamedata.url}/FurnitureData.json?v=1", - "productdata.url": "${gamedata.url}/ProductData.json?v=1", - "avatar.actions.url": "${gamedata.url}/HabboAvatarActions.json?v=1", - "avatar.figuredata.url": "${gamedata.url}/FigureData.json?v=1", - "avatar.figuremap.url": "${gamedata.url}/FigureMap.json?v=1", - "avatar.effectmap.url": "${gamedata.url}/EffectMap.json?v=1", - "avatar.asset.url": "${asset.url}/figure/%libname%.nitro", - "avatar.asset.effect.url": "${asset.url}/effect/%libname%.nitro", - "furni.asset.url": "${asset.url}/furniture/%libname%.nitro", - "furni.asset.icon.url": "${hof.furni.url}/icons/%libname%%param%_icon.png", - "pet.asset.url": "${asset.url}/pets/%libname%.nitro", - "generic.asset.url": "${asset.url}/generic/%libname%.nitro", - "badge.asset.url": "${image.library.url}album1584/%badgename%.gif", - "furni.rotation.bounce.steps": 20, - "furni.rotation.bounce.height": 0.0625, - "enable.avatar.arrow": false, - "system.log.debug": true, - "system.log.warn": true, - "system.log.error": true, - "system.log.events": false, - "system.log.packets": true, - "system.fps.animation": 24, - "system.fps.max": 60, - "system.pong.manually": true, - "system.pong.interval.ms": 20000, - "room.color.skip.transition": true, - "room.landscapes.enabled": true, - "room.zoom.enabled": true, - "avatar.mandatory.libraries": [ - "bd:1", - "li:0" - ], - "avatar.mandatory.effect.libraries": [ - "dance.1", - "dance.2", - "dance.3", - "dance.4" - ], - "avatar.default.figuredata": { - "palettes": [ - { - "id": 1, - "colors": [ - { - "id": 99999, - "index": 1001, - "club": 0, - "selectable": false, - "hexCode": "DDDDDD" - }, - { - "id": 99998, - "index": 1001, - "club": 0, - "selectable": false, - "hexCode": "FAFAFA" - } - ] - }, - { - "id": 3, - "colors": [ - { - "id": 10001, - "index": 1001, - "club": 0, - "selectable": false, - "hexCode": "EEEEEE" - }, - { - "id": 10002, - "index": 1002, - "club": 0, - "selectable": false, - "hexCode": "FA3831" - }, - { - "id": 10003, - "index": 1003, - "club": 0, - "selectable": false, - "hexCode": "FD92A0" - }, - { - "id": 10004, - "index": 1004, - "club": 0, - "selectable": false, - "hexCode": "2AC7D2" - }, - { - "id": 10005, - "index": 1005, - "club": 0, - "selectable": false, - "hexCode": "35332C" - }, - { - "id": 10006, - "index": 1006, - "club": 0, - "selectable": false, - "hexCode": "EFFF92" - }, - { - "id": 10007, - "index": 1007, - "club": 0, - "selectable": false, - "hexCode": "C6FF98" - }, - { - "id": 10008, - "index": 1008, - "club": 0, - "selectable": false, - "hexCode": "FF925A" - }, - { - "id": 10009, - "index": 1009, - "club": 0, - "selectable": false, - "hexCode": "9D597E" - }, - { - "id": 10010, - "index": 1010, - "club": 0, - "selectable": false, - "hexCode": "B6F3FF" - }, - { - "id": 10011, - "index": 1011, - "club": 0, - "selectable": false, - "hexCode": "6DFF33" - }, - { - "id": 10012, - "index": 1012, - "club": 0, - "selectable": false, - "hexCode": "3378C9" - }, - { - "id": 10013, - "index": 1013, - "club": 0, - "selectable": false, - "hexCode": "FFB631" - }, - { - "id": 10014, - "index": 1014, - "club": 0, - "selectable": false, - "hexCode": "DFA1E9" - }, - { - "id": 10015, - "index": 1015, - "club": 0, - "selectable": false, - "hexCode": "F9FB32" - }, - { - "id": 10016, - "index": 1016, - "club": 0, - "selectable": false, - "hexCode": "CAAF8F" - }, - { - "id": 10017, - "index": 1017, - "club": 0, - "selectable": false, - "hexCode": "C5C6C5" - }, - { - "id": 10018, - "index": 1018, - "club": 0, - "selectable": false, - "hexCode": "47623D" - }, - { - "id": 10019, - "index": 1019, - "club": 0, - "selectable": false, - "hexCode": "8A8361" - }, - { - "id": 10020, - "index": 1020, - "club": 0, - "selectable": false, - "hexCode": "FF8C33" - }, - { - "id": 10021, - "index": 1021, - "club": 0, - "selectable": false, - "hexCode": "54C627" - }, - { - "id": 10022, - "index": 1022, - "club": 0, - "selectable": false, - "hexCode": "1E6C99" - }, - { - "id": 10023, - "index": 1023, - "club": 0, - "selectable": false, - "hexCode": "984F88" - }, - { - "id": 10024, - "index": 1024, - "club": 0, - "selectable": false, - "hexCode": "77C8FF" - }, - { - "id": 10025, - "index": 1025, - "club": 0, - "selectable": false, - "hexCode": "FFC08E" - }, - { - "id": 10026, - "index": 1026, - "club": 0, - "selectable": false, - "hexCode": "3C4B87" - }, - { - "id": 10027, - "index": 1027, - "club": 0, - "selectable": false, - "hexCode": "7C2C47" - }, - { - "id": 10028, - "index": 1028, - "club": 0, - "selectable": false, - "hexCode": "D7FFE3" - }, - { - "id": 10029, - "index": 1029, - "club": 0, - "selectable": false, - "hexCode": "8F3F1C" - }, - { - "id": 10030, - "index": 1030, - "club": 0, - "selectable": false, - "hexCode": "FF6393" - }, - { - "id": 10031, - "index": 1031, - "club": 0, - "selectable": false, - "hexCode": "1F9B79" - }, - { - "id": 10032, - "index": 1032, - "club": 0, - "selectable": false, - "hexCode": "FDFF33" - } - ] - } - ], - "setTypes": [ - { - "type": "hd", - "paletteId": 1, - "mandatory_f_0": true, - "mandatory_f_1": true, - "mandatory_m_0": true, - "mandatory_m_1": true, - "sets": [ - { - "id": 99999, - "gender": "U", - "club": 0, - "colorable": true, - "selectable": false, - "preselectable": false, - "sellable": false, - "parts": [ - { - "id": 1, - "type": "bd", - "colorable": true, - "index": 0, - "colorindex": 1 - }, - { - "id": 1, - "type": "hd", - "colorable": true, - "index": 0, - "colorindex": 1 - }, - { - "id": 1, - "type": "lh", - "colorable": true, - "index": 0, - "colorindex": 1 - }, - { - "id": 1, - "type": "rh", - "colorable": true, - "index": 0, - "colorindex": 1 - } - ] - } - ] - }, - { - "type": "bds", - "paletteId": 1, - "mandatory_f_0": false, - "mandatory_f_1": false, - "mandatory_m_0": false, - "mandatory_m_1": false, - "sets": [ - { - "id": 10001, - "gender": "U", - "club": 0, - "colorable": true, - "selectable": false, - "preselectable": false, - "sellable": false, - "parts": [ - { - "id": 10001, - "type": "bds", - "colorable": true, - "index": 0, - "colorindex": 1 - }, - { - "id": 10001, - "type": "lhs", - "colorable": true, - "index": 0, - "colorindex": 1 - }, - { - "id": 10001, - "type": "rhs", - "colorable": true, - "index": 0, - "colorindex": 1 - } - ], - "hiddenLayers": [ - { - "partType": "bd" - }, - { - "partType": "rh" - }, - { - "partType": "lh" - } - ] - } - ] - }, - { - "type": "ss", - "paletteId": 3, - "mandatory_f_0": false, - "mandatory_f_1": false, - "mandatory_m_0": false, - "mandatory_m_1": false, - "sets": [ - { - "id": 10010, - "gender": "F", - "club": 0, - "colorable": true, - "selectable": false, - "preselectable": false, - "sellable": false, - "parts": [ - { - "id": 10001, - "type": "ss", - "colorable": true, - "index": 0, - "colorindex": 1 - } - ], - "hiddenLayers": [ - { - "partType": "ch" - }, - { - "partType": "lg" - }, - { - "partType": "ca" - }, - { - "partType": "wa" - }, - { - "partType": "sh" - }, - { - "partType": "ls" - }, - { - "partType": "rs" - }, - { - "partType": "lc" - }, - { - "partType": "rc" - }, - { - "partType": "cc" - }, - { - "partType": "cp" - } - ] - }, - { - "id": 10011, - "gender": "M", - "club": 0, - "colorable": true, - "selectable": false, - "preselectable": false, - "sellable": false, - "parts": [ - { - "id": 10002, - "type": "ss", - "colorable": true, - "index": 0, - "colorindex": 1 - } - ], - "hiddenLayers": [ - { - "partType": "ch" - }, - { - "partType": "lg" - }, - { - "partType": "ca" - }, - { - "partType": "wa" - }, - { - "partType": "sh" - }, - { - "partType": "ls" - }, - { - "partType": "rs" - }, - { - "partType": "lc" - }, - { - "partType": "rc" - }, - { - "partType": "cc" - }, - { - "partType": "cp" - } - ] - } - ] - } - ] - }, - "avatar.default.actions": { - "actions": [ - { - "id": "Default", - "state": "std", - "precedence": 1000, - "main": true, - "isDefault": true, - "geometryType": "vertical", - "activePartSet": "figure", - "assetPartDefinition": "std" - } - ] - }, - "pet.types": [ - "dog", - "cat", - "croco", - "terrier", - "bear", - "pig", - "lion", - "rhino", - "spider", - "turtle", - "chicken", - "frog", - "dragon", - "monster", - "monkey", - "horse", - "monsterplant", - "bunnyeaster", - "bunnyevil", - "bunnydepressed", - "bunnylove", - "pigeongood", - "pigeonevil", - "demonmonkey", - "bearbaby", - "terrierbaby", - "gnome", - "gnome", - "kittenbaby", - "puppybaby", - "pigletbaby", - "haloompa", - "fools", - "pterosaur", - "velociraptor", - "cow", - "LeetPen", - "bbwibb", - "elephants" - ], - "preload.assets.urls": [ - "${asset.url}/generic/avatar_additions.nitro", - "${asset.url}/generic/group_badge.nitro", - "${asset.url}/generic/floor_editor.nitro", - "${images.url}/loading_icon.png", - "${images.url}/clear_icon.png", - "${images.url}/big_arrow.png" - ] } diff --git a/public/ui-config.json b/public/ui-config.json index b0a4864..04b4a20 100644 --- a/public/ui-config.json +++ b/public/ui-config.json @@ -1,16 +1,21 @@ { + "external.plugins": [ + "plugins/room-builder.js" + ], "image.library.notifications.url": "${image.library.url}notifications/%image%.png", "achievements.images.url": "${image.library.url}Quests/%image%.png", - "camera.url": "http://192.168.0.8/camera/photo", - "thumbnails.url": "http://192.168.0.8/camera/photo/thumb/%thumbnail%.png", + "camera.url": "/swf/usercontent/camera/", + "thumbnails.url": "/swf/usercontent/thumbnails/%thumbnail%.png", "url.prefix": "", - "habbopages.url": "/gamedata/habbopages/", + "habbopages.url": "/swf/habbopages/", "group.homepage.url": "${url.prefix}/groups/%groupid%/id", "guide.help.alpha.groupid": 0, "chat.viewer.height.percentage": 0.4, + "pathfinder.underpass.height": 1.5, "widget.dimmer.colorwheel": false, "avatar.wardrobe.max.slots": 10, - "user.badges.max.slots": 5, + "user.badges.max.slots": 6, + "user.badges.group.slot.enabled": false, "user.tags.enabled": false, "camera.publish.disabled": false, "hc.disabled": false, @@ -168,6 +173,1107 @@ "name": "9" } ], + "backgrounds.data": [{ + "backgroundId": 0, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 1, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 2, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 3, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 4, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 5, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 6, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 7, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 8, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 9, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 10, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 11, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 12, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 13, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 14, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 15, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 16, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 17, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 18, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 19, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 20, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 21, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 22, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 23, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 24, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 25, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 26, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 27, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 28, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 29, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 30, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 31, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 32, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 33, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 34, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 35, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 36, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 37, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 38, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 39, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 40, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 41, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 42, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 43, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 44, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 45, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 46, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 47, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 48, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 49, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 50, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 51, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 52, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 53, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 54, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 55, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 56, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 57, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 58, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 59, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 60, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 61, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 62, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 63, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 64, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 65, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 66, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 67, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 68, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 69, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 70, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 71, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 72, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 73, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 74, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 75, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 76, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 77, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 78, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 79, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 80, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 81, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 82, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 83, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 84, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 85, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 86, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 87, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 88, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 89, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 90, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 91, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 92, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 93, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 94, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 95, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 96, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 97, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 98, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 99, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 100, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 101, + "minRank": 2, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "backgroundId": 102, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 103, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 104, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 105, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 106, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 107, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 108, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 109, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 110, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 111, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 112, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 113, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 114, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 115, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 116, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 117, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 118, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 119, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 120, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 121, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 122, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 123, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 124, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 125, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 126, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 127, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 128, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 129, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 130, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 131, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 132, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 133, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 134, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 135, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 136, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 137, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 138, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 139, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 140, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 141, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 142, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 143, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 144, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 145, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 146, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 147, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 148, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 149, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 150, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 151, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 152, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 153, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 154, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 155, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 156, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 157, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 158, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 159, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 160, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 161, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 162, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 163, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 164, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 165, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 166, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 167, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 168, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 169, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 170, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 171, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 172, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 173, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 174, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 175, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 176, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 177, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 178, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 179, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 180, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 181, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 182, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 183, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 184, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 185, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 186, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "backgroundId": 187, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + } + ], + "stands.data": [{ + "standId": 0, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 1, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 2, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 3, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 4, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 5, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 6, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 7, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 8, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 9, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 10, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 11, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 12, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 13, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 14, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 15, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "standId": 16, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "standId": 17, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "standId": 18, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "standId": 19, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "standId": 20, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "standId": 21, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + } + ], + "overlays.data": [{ + "overlayId": 0, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "overlayId": 1, + "minRank": 0, + "isHcOnly": false, + "isAmbassadorOnly": false + }, { + "overlayId": 2, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 3, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 4, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 5, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 6, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 7, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + }, { + "overlayId": 8, + "minRank": 0, + "isHcOnly": true, + "isAmbassadorOnly": false + } + ], "hotelview": { "room.pool": "791", "room.picnic": "2193", @@ -201,7 +1307,7 @@ }, "images": { "background": "${asset.url}/images/reception/stretch_blue.png", - "background.colour": "#8ee0ff", + "background.colour": "#8ee0f0", "sun": "${asset.url}/images/reception/sun.png", "drape": "${asset.url}/images/reception/drape.png", "left": "", @@ -242,9 +1348,8 @@ "catalog.asset.url": "${image.library.url}catalogue", "catalog.asset.image.url": "${catalog.asset.url}/%name%.gif", "catalog.asset.icon.url": "${catalog.asset.url}/icon_%name%.png", - "catalog.tab.icons": true, + "catalog.tab.icons": false, "catalog.headers": false, - "catalog.style": "old", "chat.input.maxlength": 100, "chat.styles.disabled": [], "chat.styles": [{ @@ -1324,4 +2429,4 @@ "image": "${image.library.url}/album1584/X1517.gif" } } -} \ No newline at end of file +} diff --git a/src/api/avatar/AvatarEditorThumbnailsHelper.ts b/src/api/avatar/AvatarEditorThumbnailsHelper.ts index ed370ee..2c21ebd 100644 --- a/src/api/avatar/AvatarEditorThumbnailsHelper.ts +++ b/src/api/avatar/AvatarEditorThumbnailsHelper.ts @@ -160,13 +160,9 @@ export class AvatarEditorThumbnailsHelper if(isDisabled) sprite.filters = [ AvatarEditorThumbnailsHelper.ALPHA_FILTER ]; - const headSize = Math.floor(texture.width * 0.5); - const cropX = Math.floor((texture.width - headSize) / 2); - const cropY = Math.floor(texture.height * 0.22); - const imageUrl = await TextureUtils.generateImageUrl({ target: sprite, - frame: new NitroRectangle(cropX, cropY, headSize, headSize) + frame: new NitroRectangle(0, 0, texture.width, texture.height) }); sprite.destroy(); diff --git a/src/api/wired/WiredActionLayoutCode.ts b/src/api/wired/WiredActionLayoutCode.ts index 7508b70..94c8f94 100644 --- a/src/api/wired/WiredActionLayoutCode.ts +++ b/src/api/wired/WiredActionLayoutCode.ts @@ -56,8 +56,4 @@ export class WiredActionLayoutCode public static USERS_HANDITEM_SELECTOR: number = 55; public static FILTER_FURNI_EXTRA: number = 56; public static FILTER_USER_EXTRA: number = 57; - public static MOVE_CARRY_USERS_EXTRA: number = 58; - public static MOVE_NO_ANIMATION_EXTRA: number = 59; - public static ANIMATION_TIME_EXTRA: number = 60; - public static MOVE_PHYSICS_EXTRA: number = 61; } diff --git a/src/components/avatar-editor/figure-set/AvatarEditorFigureSetItemView.tsx b/src/components/avatar-editor/figure-set/AvatarEditorFigureSetItemView.tsx index ac864c5..fb33358 100644 --- a/src/components/avatar-editor/figure-set/AvatarEditorFigureSetItemView.tsx +++ b/src/components/avatar-editor/figure-set/AvatarEditorFigureSetItemView.tsx @@ -51,7 +51,7 @@ export const AvatarEditorFigureSetItemView: FC<{ if(!partItem) return null; return ( - + { !partItem.isClear && isHC && } { partItem.isClear && } { !partItem.isClear && partItem.partSet.isSellable && } diff --git a/src/components/catalog/CatalogAdminContext.tsx b/src/components/catalog/CatalogAdminContext.tsx deleted file mode 100644 index 5a5fe18..0000000 --- a/src/components/catalog/CatalogAdminContext.tsx +++ /dev/null @@ -1,296 +0,0 @@ -import { CatalogAdminCreateOfferComposer, CatalogAdminCreatePageComposer, CatalogAdminDeleteOfferComposer, CatalogAdminDeletePageComposer, CatalogAdminMoveOfferComposer, CatalogAdminMovePageComposer, CatalogAdminPublishComposer, CatalogAdminResultEvent, CatalogAdminSaveOfferComposer, CatalogAdminSavePageComposer } from '@nitrots/nitro-renderer'; -import { createContext, FC, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react'; -import { ICatalogNode, IPurchasableOffer, NotificationAlertType, SendMessageComposer } from '../../api'; -import { useMessageEvent, useNotification } from '../../hooks'; - -export interface IPageEditData -{ - pageId?: number; - caption: string; - parentId: number; - pageLayout: string; - enabled: string; - visible: string; - minRank: number; - clubOnly?: string; - orderNum: number; - pageHeadline?: string; - pageTeaser?: string; - pageSpecial?: string; - pageText1?: string; - pageText2?: string; - pageTextDetails?: string; - pageTextTeaser?: string; -} - -export interface IOfferEditData -{ - offerId?: number; - pageId: number; - itemIds: string; - catalogName: string; - costCredits: number; - costPoints: number; - pointsType: number; - amount: number; - clubOnly: string; - extradata: string; - haveOffer: string; - offerId_group: number; - limitedStack: number; - orderNumber: number; -} - -interface ICatalogAdminContext -{ - adminMode: boolean; - setAdminMode: (value: boolean) => void; - editingOffer: IPurchasableOffer | null; - setEditingOffer: (offer: IPurchasableOffer | null) => void; - editingPageData: boolean; - setEditingPageData: (value: boolean) => void; - editingRootPage: boolean; - setEditingRootPage: (value: boolean) => void; - editingPageNode: ICatalogNode | null; - setEditingPageNode: (node: ICatalogNode | null) => void; - loading: boolean; - lastError: string | null; - savePage: (data: IPageEditData) => void; - createPage: (data: IPageEditData) => void; - deletePage: (pageId: number) => void; - saveOffer: (data: IOfferEditData) => void; - createOffer: (data: IOfferEditData) => void; - deleteOffer: (offerId: number) => void; - reorderOffers: (orders: { id: number; orderNumber: number }[]) => void; - reorderPage: (pageId: number, newParentId: number, newIndex: number) => void; - togglePageEnabled: (pageId: number) => void; - togglePageVisible: (pageId: number) => void; - publishCatalog: () => void; - hasPendingChanges: boolean; -} - -const CatalogAdminContext = createContext(null); - -export const useCatalogAdmin = () => useContext(CatalogAdminContext); - -export const CatalogAdminProvider: FC<{ children: ReactNode }> = ({ children }) => -{ - const [ adminMode, setAdminMode ] = useState(false); - const [ editingOffer, setEditingOffer ] = useState(null); - const [ editingPageData, setEditingPageData ] = useState(false); - const [ editingRootPage, setEditingRootPage ] = useState(false); - const [ editingPageNode, setEditingPageNode ] = useState(null); - const [ loading, setLoading ] = useState(false); - const [ lastError, setLastError ] = useState(null); - const [ hasPendingChanges, setHasPendingChanges ] = useState(false); - const pendingActionRef = useRef(null); - const { simpleAlert = null } = useNotification(); - - // Keyboard shortcuts: Esc to close edit panels - useEffect(() => - { - if(!adminMode) return; - - const handleKeyDown = (e: KeyboardEvent) => - { - if(e.key === 'Escape') - { - if(editingOffer) { setEditingOffer(null); e.preventDefault(); return; } - if(editingPageData || editingRootPage || editingPageNode) - { - setEditingPageData(false); - setEditingRootPage(false); - setEditingPageNode(null); - e.preventDefault(); - } - } - }; - - window.addEventListener('keydown', handleKeyDown); - - return () => window.removeEventListener('keydown', handleKeyDown); - }, [ adminMode, editingOffer, editingPageData, editingRootPage, editingPageNode ]); - - useMessageEvent(CatalogAdminResultEvent, (event: CatalogAdminResultEvent) => - { - const parser = event.getParser(); - const action = pendingActionRef.current; - - pendingActionRef.current = null; - setLoading(false); - - if(!parser.success) - { - setLastError(parser.message || 'Operation failed'); - - if(simpleAlert) - { - simpleAlert(parser.message || 'Operation failed', NotificationAlertType.ALERT, null, null, 'Admin Error'); - } - } - else - { - setLastError(null); - setEditingOffer(null); - setEditingPageData(false); - setEditingRootPage(false); - setEditingPageNode(null); - - if(action === 'publish') - { - setHasPendingChanges(false); - } - else - { - setHasPendingChanges(true); - } - - if(simpleAlert && action) - { - const messages: Record = { - 'savePage': 'Page saved (publish to apply)', - 'createPage': 'Page created (publish to apply)', - 'deletePage': 'Page deleted (publish to apply)', - 'saveOffer': 'Offer saved (publish to apply)', - 'createOffer': 'Offer created (publish to apply)', - 'deleteOffer': 'Offer deleted (publish to apply)', - 'reorder': 'Order updated (publish to apply)', - 'toggleEnabled': 'Page toggled (publish to apply)', - 'toggleVisible': 'Visibility toggled (publish to apply)', - 'movePage': 'Page moved (publish to apply)', - 'publish': 'Catalog published! All users updated.', - }; - - simpleAlert(messages[action] || 'Operation completed', NotificationAlertType.DEFAULT, null, null, 'Catalog Admin'); - } - } - }); - - const savePage = useCallback((data: IPageEditData) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'savePage'; - SendMessageComposer(new CatalogAdminSavePageComposer( - data.pageId || 0, data.caption, data.caption, data.pageLayout, 0, - data.minRank, data.visible === '1', data.enabled === '1', - data.orderNum, data.parentId, - data.pageHeadline || '', data.pageTeaser || '', data.pageTextDetails || '' - )); - }, []); - - const createPage = useCallback((data: IPageEditData) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'createPage'; - SendMessageComposer(new CatalogAdminCreatePageComposer( - data.caption, data.caption, data.pageLayout, 0, - data.minRank, data.visible === '1', data.enabled === '1', - data.orderNum, data.parentId - )); - }, []); - - const deletePage = useCallback((pageId: number) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'deletePage'; - SendMessageComposer(new CatalogAdminDeletePageComposer(pageId)); - }, []); - - const saveOffer = useCallback((data: IOfferEditData) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'saveOffer'; - SendMessageComposer(new CatalogAdminSaveOfferComposer( - data.offerId || 0, data.pageId, parseInt(data.itemIds) || 0, - data.catalogName, data.costCredits, data.costPoints, data.pointsType, - data.amount, data.clubOnly === '1' ? 1 : 0, data.extradata, - data.haveOffer === '1', data.offerId_group, data.limitedStack, data.orderNumber - )); - }, []); - - const createOffer = useCallback((data: IOfferEditData) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'createOffer'; - SendMessageComposer(new CatalogAdminCreateOfferComposer( - data.pageId, parseInt(data.itemIds) || 0, - data.catalogName, data.costCredits, data.costPoints, data.pointsType, - data.amount, data.clubOnly === '1' ? 1 : 0, data.extradata, - data.haveOffer === '1', data.offerId_group, data.limitedStack, data.orderNumber - )); - }, []); - - const deleteOffer = useCallback((offerId: number) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'deleteOffer'; - SendMessageComposer(new CatalogAdminDeleteOfferComposer(offerId)); - }, []); - - const reorderOffers = useCallback((orders: { id: number; orderNumber: number }[]) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'reorder'; - - for(const order of orders) - { - SendMessageComposer(new CatalogAdminMoveOfferComposer(order.id, order.orderNumber)); - } - }, []); - - const reorderPage = useCallback((pageId: number, newParentId: number, newIndex: number) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'movePage'; - SendMessageComposer(new CatalogAdminMovePageComposer(pageId, newParentId, newIndex)); - }, []); - - const togglePageEnabled = useCallback((pageId: number) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'toggleEnabled'; - SendMessageComposer(new CatalogAdminMovePageComposer(pageId, -1, -1)); - }, []); - - const togglePageVisible = useCallback((pageId: number) => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'toggleVisible'; - SendMessageComposer(new CatalogAdminMovePageComposer(pageId, -2, -1)); - }, []); - - const publishCatalog = useCallback(() => - { - setLoading(true); - setLastError(null); - pendingActionRef.current = 'publish'; - SendMessageComposer(new CatalogAdminPublishComposer()); - }, []); - - return ( - - { children } - - ); -}; diff --git a/src/components/catalog/CatalogClassicView.tsx b/src/components/catalog/CatalogClassicView.tsx deleted file mode 100644 index a5fabd4..0000000 --- a/src/components/catalog/CatalogClassicView.tsx +++ /dev/null @@ -1,183 +0,0 @@ -import { AddLinkEventTracker, GetSessionDataManager, ILinkEventTracker, RemoveLinkEventTracker } from '@nitrots/nitro-renderer'; -import { FC, useEffect } from 'react'; -import { FaCog, FaEdit, FaEye, FaEyeSlash, FaPlus, FaTrash } from 'react-icons/fa'; -import { GetConfigurationValue, LocalizeText } from '../../api'; -import { Column, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common'; -import { useCatalog } from '../../hooks'; -import { CatalogAdminProvider, useCatalogAdmin } from './CatalogAdminContext'; -import { CatalogAdminOfferEditView } from './views/admin/CatalogAdminOfferEditView'; -import { CatalogAdminPageEditView } from './views/admin/CatalogAdminPageEditView'; -import { CatalogIconView } from './views/catalog-icon/CatalogIconView'; -import { CatalogGiftView } from './views/gift/CatalogGiftView'; -import { CatalogNavigationView } from './views/navigation/CatalogNavigationView'; -import { GetCatalogLayout } from './views/page/layout/GetCatalogLayout'; -import { MarketplacePostOfferView } from './views/page/layout/marketplace/MarketplacePostOfferView'; - -const CatalogClassicViewInner: FC<{}> = () => -{ - const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, openPageByName = null, openPageByOfferId = null, activateNode = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const adminMode = catalogAdmin?.adminMode ?? false; - const setAdminMode = catalogAdmin?.setAdminMode ?? (() => {}); - const hasPendingChanges = catalogAdmin?.hasPendingChanges ?? false; - const publishCatalog = catalogAdmin?.publishCatalog ?? (() => {}); - const loading = catalogAdmin?.loading ?? false; - - const isMod = GetSessionDataManager().isModerator; - - useEffect(() => - { - const linkTracker: ILinkEventTracker = { - linkReceived: (url: string) => - { - const parts = url.split('/'); - - if(parts.length < 2) return; - - switch(parts[1]) - { - case 'show': - setIsVisible(true); - return; - case 'hide': - setIsVisible(false); - return; - case 'toggle': - setIsVisible(prevValue => !prevValue); - return; - case 'open': - if(parts.length > 2) - { - if(parts.length === 4) - { - switch(parts[2]) - { - case 'offerId': - openPageByOfferId(parseInt(parts[3])); - return; - } - } - else - { - openPageByName(parts[2]); - } - } - else - { - setIsVisible(true); - } - - return; - } - }, - eventUrlPrefix: 'catalog/' - }; - - AddLinkEventTracker(linkTracker); - - return () => RemoveLinkEventTracker(linkTracker); - }, [ setIsVisible, openPageByOfferId, openPageByName ]); - - return ( - <> - { isVisible && - - setIsVisible(false) } /> - { /* Admin banner */ } - { adminMode && -
- โš™ Admin Mode - -
} - - { rootNode && (rootNode.children.length > 0) && rootNode.children.map((child, index) => - { - if(!adminMode && !child.isVisible) return null; - - const isHidden = !child.isVisible; - - return ( - - { - if(searchResult) setSearchResult(null); - - activateNode(child); - } } > -
- { GetConfigurationValue('catalog.tab.icons') && } - { child.localization } - { adminMode && isHidden && } - { adminMode && -
e.stopPropagation() }> - { catalogAdmin.setEditingPageNode(child); catalogAdmin.setEditingRootPage(false); catalogAdmin.setEditingPageData(true); } } /> - catalogAdmin.togglePageVisible(child.pageId) }> - { isHidden ? : } - - { if(confirm(LocalizeText('catalog.admin.delete.category.confirm', [ 'name' ], [ child.localization ]))) catalogAdmin.deletePage(child.pageId); } } /> -
} -
-
- ); - }) } - { /* Admin toggle button in tabs bar */ } - { isMod && - setAdminMode(!adminMode) }> - - } -
- - { /* Admin: add new root category */ } - { adminMode && rootNode && -
- - -
} - - { !navigationHidden && - - { activeNodes && (activeNodes.length > 0) && - } - } - - { adminMode && } - { GetCatalogLayout(currentPage, () => setNavigationHidden(true)) } - - -
-
} - - - - - ); -}; - -export const CatalogClassicView: FC<{}> = () => -{ - return ( - - - - ); -}; diff --git a/src/components/catalog/CatalogModernView.tsx b/src/components/catalog/CatalogModernView.tsx deleted file mode 100644 index 958e3ea..0000000 --- a/src/components/catalog/CatalogModernView.tsx +++ /dev/null @@ -1,291 +0,0 @@ -import { AddLinkEventTracker, GetSessionDataManager, ILinkEventTracker, RemoveLinkEventTracker } from '@nitrots/nitro-renderer'; -import { FC, useEffect, useState } from 'react'; -import { FaCog, FaEdit, FaEye, FaEyeSlash, FaHeart, FaPlus, FaStar, FaTrash } from 'react-icons/fa'; -import { LocalizeText } from '../../api'; -import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common'; -import { useCatalog, useCatalogFavorites } from '../../hooks'; -import { CatalogAdminProvider, useCatalogAdmin } from './CatalogAdminContext'; -import { CatalogAdminOfferEditView } from './views/admin/CatalogAdminOfferEditView'; -import { CatalogAdminPageEditView } from './views/admin/CatalogAdminPageEditView'; -import { CatalogIconView } from './views/catalog-icon/CatalogIconView'; -import { CatalogFavoritesView } from './views/favorites/CatalogFavoritesView'; -import { CatalogGiftView } from './views/gift/CatalogGiftView'; -import { CatalogNavigationView } from './views/navigation/CatalogNavigationView'; -import { CatalogSearchView } from './views/page/common/CatalogSearchView'; -import { GetCatalogLayout } from './views/page/layout/GetCatalogLayout'; -import { MarketplacePostOfferView } from './views/page/layout/marketplace/MarketplacePostOfferView'; - -const CatalogModernViewInner: FC<{}> = () => -{ - const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, openPageByName = null, openPageByOfferId = null, activateNode = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const adminMode = catalogAdmin?.adminMode ?? false; - const setAdminMode = catalogAdmin?.setAdminMode ?? (() => {}); - const hasPendingChanges = catalogAdmin?.hasPendingChanges ?? false; - const publishCatalog = catalogAdmin?.publishCatalog ?? (() => {}); - const loading = catalogAdmin?.loading ?? false; - const { favoriteOfferIds, favoritePageIds } = useCatalogFavorites(); - const [ showFavorites, setShowFavorites ] = useState(false); - - const isMod = GetSessionDataManager().isModerator; - const totalFavs = favoriteOfferIds.length + favoritePageIds.length; - - useEffect(() => - { - const linkTracker: ILinkEventTracker = { - linkReceived: (url: string) => - { - const parts = url.split('/'); - - if(parts.length < 2) return; - - switch(parts[1]) - { - case 'show': - setIsVisible(true); - return; - case 'hide': - setIsVisible(false); - return; - case 'toggle': - setIsVisible(prevValue => !prevValue); - return; - case 'open': - if(parts.length > 2) - { - if(parts.length === 4) - { - switch(parts[2]) - { - case 'offerId': - openPageByOfferId(parseInt(parts[3])); - return; - } - } - else - { - openPageByName(parts[2]); - } - } - else - { - setIsVisible(true); - } - - return; - } - }, - eventUrlPrefix: 'catalog/' - }; - - AddLinkEventTracker(linkTracker); - - return () => RemoveLinkEventTracker(linkTracker); - }, [ setIsVisible, openPageByOfferId, openPageByName ]); - - return ( - <> - { isVisible && - - setIsVisible(false) } /> - - { /* Admin banner */ } - { adminMode && -
- โš™ Admin Mode - -
} - -
- { /* === LEFT SIDEBAR === */ } -
- - { /* Favorites toggle */ } -
setShowFavorites(!showFavorites) } - > -
- 0 ? 'text-danger' : 'text-muted' }` } /> - { totalFavs > 0 && - - { totalFavs } - } -
- { LocalizeText('catalog.favorites') } -
- -
- - { /* Admin: root page actions */ } - { adminMode && rootNode && -
- - -
} - - { /* Category icons */ } - { rootNode && rootNode.children.length > 0 && rootNode.children.map((child, index) => - { - if(!adminMode && !child.isVisible) return null; - - const isHidden = !child.isVisible; - - return ( -
- { - if(searchResult) setSearchResult(null); - if(showFavorites) setShowFavorites(false); - activateNode(child); - } } - > -
- - { isHidden && } -
- - { child.localization } - - { /* Admin actions on each root category */ } - { adminMode && -
-
- { - e.stopPropagation(); - catalogAdmin.setEditingPageNode(child); - catalogAdmin.setEditingRootPage(false); - catalogAdmin.setEditingPageData(true); - } } - > - -
-
- { - e.stopPropagation(); - catalogAdmin.togglePageVisible(child.pageId); - } } - > - { isHidden - ? - : } -
-
- { - e.stopPropagation(); - if(confirm(LocalizeText('catalog.admin.delete.category.confirm', [ 'name' ], [ child.localization ]))) - { - catalogAdmin.deletePage(child.pageId); - } - } } - > - -
-
} -
- ); - }) } -
- - { /* === MAIN AREA === */ } -
- { /* Toolbar: search + admin */ } -
- { /* Breadcrumb */ } -
- - { activeNodes && activeNodes.length > 0 - ? activeNodes.map((node, i) => ( - - { i > 0 && โ€บ } - activateNode(node) : undefined }> - { node.localization } - - - )) - : { LocalizeText('catalog.title') } } -
- -
- -
- - { isMod && - } -
- - { /* Content area */ } -
- { showFavorites - ?
- setShowFavorites(false) } /> -
- : <> - { !navigationHidden && activeNodes && activeNodes.length > 0 && -
- -
} -
- { adminMode && } - { GetCatalogLayout(currentPage, () => setNavigationHidden(true)) } -
- } -
-
-
- - } - - - - - ); -}; - -export const CatalogModernView: FC<{}> = () => -{ - return ( - - - - ); -}; diff --git a/src/components/catalog/CatalogView.tsx b/src/components/catalog/CatalogView.tsx index fb63d63..fc5f633 100644 --- a/src/components/catalog/CatalogView.tsx +++ b/src/components/catalog/CatalogView.tsx @@ -1,22 +1,111 @@ -import { FC } from 'react'; -import { GetConfigurationValue } from '../../api'; -import { CatalogClassicView } from './CatalogClassicView'; -import { CatalogModernView } from './CatalogModernView'; +import { AddLinkEventTracker, ILinkEventTracker, RemoveLinkEventTracker } from '@nitrots/nitro-renderer'; +import { FC, useEffect } from 'react'; +import { GetConfigurationValue, LocalizeText } from '../../api'; +import { Column, Grid, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common'; +import { useCatalog } from '../../hooks'; +import { CatalogIconView } from './views/catalog-icon/CatalogIconView'; +import { CatalogGiftView } from './views/gift/CatalogGiftView'; +import { CatalogNavigationView } from './views/navigation/CatalogNavigationView'; +import { GetCatalogLayout } from './views/page/layout/GetCatalogLayout'; +import { MarketplacePostOfferView } from './views/page/layout/marketplace/MarketplacePostOfferView'; -export const CatalogView: FC<{}> = () => +export const CatalogView: FC<{}> = props => { - const style = GetConfigurationValue('catalog.style', 'classic'); + const { isVisible = false, setIsVisible = null, rootNode = null, currentPage = null, navigationHidden = false, setNavigationHidden = null, activeNodes = [], searchResult = null, setSearchResult = null, openPageByName = null, openPageByOfferId = null, activateNode = null, getNodeById } = useCatalog(); - if(style === 'new') return ; + useEffect(() => + { + const linkTracker: ILinkEventTracker = { + linkReceived: (url: string) => + { + const parts = url.split('/'); - return ; -}; + if(parts.length < 2) return; + + switch(parts[1]) + { + case 'show': + setIsVisible(true); + return; + case 'hide': + setIsVisible(false); + return; + case 'toggle': + setIsVisible(prevValue => !prevValue); + return; + case 'open': + if(parts.length > 2) + { + if(parts.length === 4) + { + switch(parts[2]) + { + case 'offerId': + openPageByOfferId(parseInt(parts[3])); + return; + } + } + else + { + openPageByName(parts[2]); + } + } + else + { + setIsVisible(true); + } + + return; + } + }, + eventUrlPrefix: 'catalog/' + }; + + AddLinkEventTracker(linkTracker); + + return () => RemoveLinkEventTracker(linkTracker); + }, [ setIsVisible, openPageByOfferId, openPageByName ]); -export const CatalogView: FC<{}> = () => -{ return ( - - - + <> + { isVisible && + + setIsVisible(false) } /> + + { rootNode && (rootNode.children.length > 0) && rootNode.children.map((child, index) => + { + if(!child.isVisible) return null; + + return ( + + { + if(searchResult) setSearchResult(null); + + activateNode(child); + } } > +
+ { GetConfigurationValue('catalog.tab.icons') && } + { child.localization } +
+
+ ); + }) } +
+ + + { !navigationHidden && + + { activeNodes && (activeNodes.length > 0) && + } + } + + { GetCatalogLayout(currentPage, () => setNavigationHidden(true)) } + + + +
} + + + ); }; diff --git a/src/components/catalog/views/admin/CatalogAdminOfferEditView.tsx b/src/components/catalog/views/admin/CatalogAdminOfferEditView.tsx deleted file mode 100644 index f6da55a..0000000 --- a/src/components/catalog/views/admin/CatalogAdminOfferEditView.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { createPortal } from 'react-dom'; -import { FaSave, FaSpinner, FaTimes, FaTrash } from 'react-icons/fa'; -import { LocalizeText } from '../../../../api'; -import { useCatalog } from '../../../../hooks'; -import { IOfferEditData, useCatalogAdmin } from '../../CatalogAdminContext'; - -export const CatalogAdminOfferEditView: FC<{}> = () => -{ - const { currentPage = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const editingOffer = catalogAdmin?.editingOffer ?? null; - const setEditingOffer = catalogAdmin?.setEditingOffer; - const saveOffer = catalogAdmin?.saveOffer; - const deleteOffer = catalogAdmin?.deleteOffer; - const createOffer = catalogAdmin?.createOffer; - const loading = catalogAdmin?.loading ?? false; - - const [ itemIds, setItemIds ] = useState('0'); - const [ catalogName, setCatalogName ] = useState(''); - const [ costCredits, setCostCredits ] = useState(0); - const [ costPoints, setCostPoints ] = useState(0); - const [ pointsType, setPointsType ] = useState(0); - const [ amount, setAmount ] = useState(1); - const [ clubOnly, setClubOnly ] = useState('0'); - const [ extradata, setExtradata ] = useState(''); - const [ haveOffer, setHaveOffer ] = useState('1'); - const [ offerId, setOfferIdGroup ] = useState(-1); - const [ limitedStack, setLimitedStack ] = useState(0); - const [ orderNumber, setOrderNumber ] = useState(0); - const [ isNew, setIsNew ] = useState(false); - - useEffect(() => - { - if(!editingOffer) return; - - if(editingOffer.offerId === -1) - { - setIsNew(true); - setItemIds('0'); - setCatalogName(''); - setCostCredits(0); - setCostPoints(0); - setPointsType(0); - setAmount(1); - setClubOnly('0'); - setExtradata(''); - setHaveOffer('1'); - setOfferIdGroup(-1); - setLimitedStack(0); - setOrderNumber(0); - } - else - { - setIsNew(false); - setItemIds(String(editingOffer.product?.productClassId || 0)); - setCatalogName(editingOffer.localizationName || ''); - setCostCredits(editingOffer.priceInCredits); - setCostPoints(editingOffer.priceInActivityPoints); - setPointsType(editingOffer.activityPointType); - setAmount(editingOffer.product?.productCount || 1); - setClubOnly(editingOffer.clubLevel > 0 ? '1' : '0'); - setExtradata(editingOffer.product?.extraParam || ''); - setHaveOffer('1'); - setOfferIdGroup(editingOffer.offerId || -1); - setLimitedStack(0); - setOrderNumber(0); - } - }, [ editingOffer ]); - - if(!editingOffer) return null; - - const handleSave = async () => - { - if(!saveOffer || !createOffer) return; - - const data: IOfferEditData = { - offerId: isNew ? undefined : editingOffer.offerId, - pageId: currentPage?.pageId || 0, - itemIds, - catalogName, - costCredits, - costPoints, - pointsType, - amount, - clubOnly, - extradata, - haveOffer, - offerId_group: offerId, - limitedStack, - orderNumber - }; - - const success = isNew ? await createOffer(data) : await saveOffer(data); - - if(success && setEditingOffer) setEditingOffer(null); - }; - - const handleDelete = () => - { - if(isNew || !deleteOffer || !confirm(LocalizeText('catalog.admin.delete.offer.confirm'))) return; - - deleteOffer(editingOffer.offerId); - if(setEditingOffer) setEditingOffer(null); - }; - - const inputClass = 'text-[11px] border-2 border-card-grid-item-border rounded px-2 py-1 bg-white focus:outline-none focus:border-primary transition-colors'; - - return createPortal( -
setEditingOffer(null) }> -
- -
e.stopPropagation() }> - { /* Header */ } -
- - { isNew ? LocalizeText('catalog.admin.offer.new') : `${ LocalizeText('catalog.admin.offer.edit') } #${ editingOffer.offerId }` } - -
setEditingOffer(null) }> - -
-
- -
- { /* Current name */ } - { !isNew && -
- { editingOffer.localizationName } -
} - - { /* Catalog Name */ } -
- - setCatalogName(e.target.value) } /> -
- - { /* Generale */ } -
-
{ LocalizeText('catalog.admin.offer.general') }
-
-
- - setItemIds(e.target.value) } /> -
-
- - setAmount(parseInt(e.target.value) || 1) } /> -
-
- - setOrderNumber(parseInt(e.target.value) || 0) } /> -
-
-
- - { /* Prezzi */ } -
-
{ LocalizeText('catalog.admin.offer.prices') }
-
-
- - setCostCredits(parseInt(e.target.value) || 0) } /> -
-
- - setCostPoints(parseInt(e.target.value) || 0) } /> -
-
- - -
-
-
- - { /* Opzioni */ } -
-
{ LocalizeText('catalog.admin.offer.options') }
-
-
- - -
-
- - setLimitedStack(parseInt(e.target.value) || 0) } /> -
-
- - setOfferIdGroup(parseInt(e.target.value) || -1) } /> -
-
-
- - setExtradata(e.target.value) } /> -
-
- setHaveOffer(e.target.checked ? '1' : '0') } /> - -
-
- - { /* Actions */ } -
- { !isNew - ? - :
} - -
-
-
-
, - document.body - ); -}; diff --git a/src/components/catalog/views/admin/CatalogAdminPageEditView.tsx b/src/components/catalog/views/admin/CatalogAdminPageEditView.tsx deleted file mode 100644 index 6fd4a07..0000000 --- a/src/components/catalog/views/admin/CatalogAdminPageEditView.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { FaSave, FaSpinner, FaTimes, FaTrash } from 'react-icons/fa'; -import { LocalizeText } from '../../../../api'; -import { useCatalog } from '../../../../hooks'; -import { IPageEditData, useCatalogAdmin } from '../../CatalogAdminContext'; - -const LAYOUT_OPTIONS = [ - 'default_3x3', 'frontpage4', 'pets', 'pets2', 'pets3', - 'spaces_new', 'soundmachine', 'trophies', 'roomads', - 'guild_frontpage', 'guild_forum', 'guild_custom_furni', - 'vip_buy', 'marketplace', 'marketplace_own_items', - 'recycler', 'recycler_info', 'recycler_prizes', - 'info_loyalty', 'badge_display', 'bots', 'single_bundle', - 'color_grouping', 'recent_purchases', 'custom_prefix' -]; - -export const CatalogAdminPageEditView: FC<{}> = () => -{ - const { currentPage = null, activeNodes = [], rootNode = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const editingPageData = catalogAdmin?.editingPageData ?? false; - const editingRootPage = catalogAdmin?.editingRootPage ?? false; - const editingPageNode = catalogAdmin?.editingPageNode ?? null; - const loading = catalogAdmin?.loading ?? false; - - const [ caption, setCaption ] = useState(''); - const [ pageLayout, setPageLayout ] = useState('default_3x3'); - const [ minRank, setMinRank ] = useState(1); - const [ visible, setVisible ] = useState('1'); - const [ enabled, setEnabled ] = useState('1'); - const [ orderNum, setOrderNum ] = useState(0); - - // Resolve what we're editing: - // 1. editingPageNode (explicit node from sidebar click) - // 2. editingRootPage (root button) - // 3. current active page (from "Modifica Pagina" in layout) - const targetNode = editingPageNode - ? editingPageNode - : editingRootPage - ? rootNode - : (activeNodes.length > 0 ? activeNodes[activeNodes.length - 1] : null); - - const targetPageId = targetNode?.pageId ?? currentPage?.pageId; - const isRoot = editingRootPage; - - const closeForm = () => - { - catalogAdmin?.setEditingPageData(false); - catalogAdmin?.setEditingRootPage(false); - catalogAdmin?.setEditingPageNode(null); - }; - - useEffect(() => - { - if(!editingPageData || !targetNode) return; - - setCaption(targetNode.localization || ''); - setPageLayout(currentPage?.layoutCode || 'default_3x3'); - setVisible(targetNode.isVisible ? '1' : '0'); - setEnabled('1'); - setMinRank(1); - setOrderNum(0); - }, [ editingPageData, targetNode, currentPage ]); - - if(!editingPageData || !targetNode) return null; - - const inputClass = 'text-[11px] border-2 border-card-grid-item-border rounded px-2 py-1 bg-white focus:outline-none focus:border-primary transition-colors'; - - const handleSave = async () => - { - if(!catalogAdmin?.savePage) return; - - const parentNode = targetNode.parent; - - const data: IPageEditData = { - pageId: targetPageId, - caption, - pageLayout, - minRank, - visible, - enabled, - orderNum, - parentId: parentNode ? parentNode.pageId : -1, - }; - - const success = await catalogAdmin.savePage(data); - - if(success) closeForm(); - }; - - const handleDelete = async () => - { - if(!catalogAdmin?.deletePage || isRoot) return; - if(!confirm(LocalizeText('catalog.admin.delete.page.confirm', [ 'name' ], [ targetNode.localization ]))) return; - - const success = await catalogAdmin.deletePage(targetPageId); - - if(success) closeForm(); - }; - - return ( -
-
- - { isRoot ? LocalizeText('catalog.admin.edit.root') : `${ LocalizeText('catalog.admin.edit') } ${ targetNode.localization } (#${ targetPageId })` } - - -
- -
-
- - setCaption(e.target.value) } /> -
-
- - setMinRank(parseInt(e.target.value) || 1) } /> -
-
- - -
-
- - setOrderNum(parseInt(e.target.value) || 0) } /> -
-
- - -
-
- -
- { !isRoot - ? - :
} - -
-
- ); -}; diff --git a/src/components/catalog/views/catalog-rail/CatalogRailItemView.tsx b/src/components/catalog/views/catalog-rail/CatalogRailItemView.tsx deleted file mode 100644 index 3b1cd21..0000000 --- a/src/components/catalog/views/catalog-rail/CatalogRailItemView.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { FC } from 'react'; -import { ICatalogNode } from '../../../../api'; -import { CatalogIconView } from '../catalog-icon/CatalogIconView'; - -interface CatalogRailItemViewProps -{ - node: ICatalogNode; - isActive: boolean; - onClick: () => void; -} - -export const CatalogRailItemView: FC = props => -{ - const { node, isActive, onClick } = props; - - return ( -
-
- -
- - { node.localization } - -
- ); -}; diff --git a/src/components/catalog/views/favorites/CatalogFavoritesView.tsx b/src/components/catalog/views/favorites/CatalogFavoritesView.tsx deleted file mode 100644 index 676f771..0000000 --- a/src/components/catalog/views/favorites/CatalogFavoritesView.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { FC, useMemo } from 'react'; -import { FaHeart, FaStar, FaTimes } from 'react-icons/fa'; -import { ICatalogNode, LocalizeText } from '../../../../api'; -import { useCatalog, useCatalogFavorites } from '../../../../hooks'; -import { CatalogIconView } from '../catalog-icon/CatalogIconView'; - -interface CatalogFavoritesViewProps -{ - onClose: () => void; -} - -export const CatalogFavoritesView: FC = props => -{ - const { onClose } = props; - const { favoriteOffers, favoritePageIds, toggleFavoritePage, toggleFavoriteOffer } = useCatalogFavorites(); - const { offersToNodes, activateNode, openPageByOfferId, rootNode } = useCatalog(); - - const favoritePages = useMemo(() => - { - if(!rootNode || favoritePageIds.length === 0) return []; - - const pages: Array<{ pageId: number; name: string; iconId: number; node: ICatalogNode }> = []; - - const findNode = (node: ICatalogNode) => - { - if(favoritePageIds.includes(node.pageId)) - { - pages.push({ pageId: node.pageId, name: node.localization, iconId: node.iconId, node }); - } - - if(node.children) - { - for(const child of node.children) findNode(child); - } - }; - - findNode(rootNode); - - return pages; - }, [ favoritePageIds, rootNode ]); - - // Enrich offers with node data if available - const enrichedOffers = useMemo(() => - { - return favoriteOffers.map(fav => - { - let nodeName: string | null = null; - let nodeIconId: number | null = null; - - if(offersToNodes) - { - const nodes = offersToNodes.get(fav.offerId); - - if(nodes && nodes.length > 0) - { - nodeName = nodes[0].localization; - nodeIconId = nodes[0].iconId; - } - } - - return { - ...fav, - displayName: fav.name || nodeName || `Offer #${ fav.offerId }`, - nodeIconId - }; - }); - }, [ favoriteOffers, offersToNodes ]); - - return ( -
- { /* Header */ } -
-
- - { LocalizeText('catalog.favorites') } - ({ enrichedOffers.length + favoritePages.length }) -
- -
- -
- { /* Favorite Pages */ } - { favoritePages.length > 0 && -
-
- - { LocalizeText('catalog.favorites.pages') } -
-
- { favoritePages.map(page => ( -
{ activateNode(page.node); onClose(); } } - > - - { page.name } - { e.stopPropagation(); toggleFavoritePage(page.pageId); } } - /> -
- )) } -
-
} - - { /* Favorite Offers */ } - { enrichedOffers.length > 0 && -
-
- - { LocalizeText('catalog.favorites.furni') } -
-
- { enrichedOffers.map(fav => ( -
{ openPageByOfferId(fav.offerId); onClose(); } } - > - { /* Furni icon */ } -
- { fav.iconUrl - ? - : fav.nodeIconId !== null - ? - : - } -
- { fav.displayName } - { e.stopPropagation(); toggleFavoriteOffer(fav.offerId); } } - /> -
- )) } -
-
} - - { /* Empty state */ } - { favoritePages.length === 0 && enrichedOffers.length === 0 && -
-
- -

{ LocalizeText('catalog.favorites.empty') }

-

{ LocalizeText('catalog.favorites.empty.hint') }

-
-
} -
-
- ); -}; diff --git a/src/components/catalog/views/navigation/CatalogBreadcrumbView.tsx b/src/components/catalog/views/navigation/CatalogBreadcrumbView.tsx deleted file mode 100644 index 60ed73a..0000000 --- a/src/components/catalog/views/navigation/CatalogBreadcrumbView.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { FC } from 'react'; -import { FaChevronRight, FaHome } from 'react-icons/fa'; -import { LocalizeText } from '../../../../api'; -import { useCatalog } from '../../../../hooks'; - -export const CatalogBreadcrumbView: FC<{}> = () => -{ - const { activeNodes = [], activateNode } = useCatalog(); - - if(!activeNodes || activeNodes.length === 0) - { - return ( -
- - { LocalizeText('catalog.title') } -
- ); - } - - return ( -
- activateNode(activeNodes[0]) } - /> - { activeNodes.map((node, i) => ( - - - activateNode(node) : undefined } - > - { node.localization } - - - )) } -
- ); -}; diff --git a/src/components/catalog/views/navigation/CatalogNavigationItemView.tsx b/src/components/catalog/views/navigation/CatalogNavigationItemView.tsx index d31d801..48ea04e 100644 --- a/src/components/catalog/views/navigation/CatalogNavigationItemView.tsx +++ b/src/components/catalog/views/navigation/CatalogNavigationItemView.tsx @@ -1,8 +1,8 @@ -import { FC, useCallback, useRef, useState } from 'react'; -import { FaArrowsAlt, FaCaretDown, FaCaretUp, FaPlus, FaStar, FaTrash } from 'react-icons/fa'; -import { ICatalogNode, LocalizeText } from '../../../../api'; -import { useCatalog, useCatalogFavorites } from '../../../../hooks'; -import { useCatalogAdmin } from '../../CatalogAdminContext'; +import { FC } from 'react'; +import { FaCaretDown, FaCaretUp } from 'react-icons/fa'; +import { ICatalogNode } from '../../../../api'; +import { LayoutGridItem, Text } from '../../../../common'; +import { useCatalog } from '../../../../hooks'; import { CatalogIconView } from '../catalog-icon/CatalogIconView'; import { CatalogNavigationSetView } from './CatalogNavigationSetView'; @@ -16,122 +16,18 @@ export const CatalogNavigationItemView: FC = pro { const { node = null, child = false } = props; const { activateNode = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const adminMode = catalogAdmin?.adminMode ?? false; - const { isFavoritePage, toggleFavoritePage } = useCatalogFavorites(); - const isFav = node ? isFavoritePage(node.pageId) : false; - const [ isDragOver, setIsDragOver ] = useState(false); - const dragRef = useRef(null); - - const handleDragStart = useCallback((e: React.DragEvent) => - { - if(!adminMode) return; - - e.dataTransfer.setData('text/plain', JSON.stringify({ pageId: node.pageId, parentId: node.parent?.pageId ?? -1 })); - e.dataTransfer.effectAllowed = 'move'; - }, [ adminMode, node ]); - - const handleDragOver = useCallback((e: React.DragEvent) => - { - if(!adminMode) return; - - e.preventDefault(); - e.dataTransfer.dropEffect = 'move'; - setIsDragOver(true); - }, [ adminMode ]); - - const handleDragLeave = useCallback(() => - { - setIsDragOver(false); - }, []); - - const handleDrop = useCallback((e: React.DragEvent) => - { - if(!adminMode) return; - - e.preventDefault(); - setIsDragOver(false); - - try - { - const data = JSON.parse(e.dataTransfer.getData('text/plain')); - - if(data.pageId && data.pageId !== node.pageId) - { - // Drop onto a branch = reparent under this node - // Drop onto a leaf = reorder as sibling - const targetParentId = node.isBranch ? node.pageId : (node.parent?.pageId ?? -1); - const targetIndex = node.isBranch ? 0 : (node.parent?.children?.indexOf(node) ?? 0); - - catalogAdmin?.reorderPage(data.pageId, targetParentId, targetIndex); - } - } - catch(err) - { - // Invalid drag data - } - }, [ adminMode, node, catalogAdmin ]); return ( -
-
activateNode(node) } - onDragLeave={ adminMode ? handleDragLeave : undefined } - onDragOver={ adminMode ? handleDragOver : undefined } - onDragStart={ adminMode ? handleDragStart : undefined } - onDrop={ adminMode ? handleDrop : undefined } - > - { adminMode && - } -
- -
- { node.localization } - { adminMode && -
- - { - e.stopPropagation(); - catalogAdmin.createPage({ - caption: 'New Page', - pageLayout: 'default_3x3', - minRank: 1, - visible: '1', - enabled: '1', - orderNum: 0, - parentId: node.pageId, - }); - } } - /> - - { - e.stopPropagation(); - if(confirm(LocalizeText('catalog.admin.delete.page.confirm', [ 'name' ], [ node.localization ]))) - { - catalogAdmin.deletePage(node.pageId); - } - } } - /> -
} - { !adminMode && node.pageId > 0 && - { e.stopPropagation(); toggleFavoritePage(node.pageId); } } - /> } +
+ activateNode(node) }> + + { node.localization } { node.isBranch && - - { node.isOpen ? : } - } -
+ <> + { node.isOpen && } + { !node.isOpen && } + } + { node.isOpen && node.isBranch && }
diff --git a/src/components/catalog/views/navigation/CatalogNavigationView.tsx b/src/components/catalog/views/navigation/CatalogNavigationView.tsx index 777c5fd..10e2a2f 100644 --- a/src/components/catalog/views/navigation/CatalogNavigationView.tsx +++ b/src/components/catalog/views/navigation/CatalogNavigationView.tsx @@ -1,6 +1,8 @@ import { FC } from 'react'; import { ICatalogNode } from '../../../../api'; +import { AutoGrid, Column } from '../../../../common'; import { useCatalog } from '../../../../hooks'; +import { CatalogSearchView } from '../page/common/CatalogSearchView'; import { CatalogNavigationItemView } from './CatalogNavigationItemView'; import { CatalogNavigationSetView } from './CatalogNavigationSetView'; @@ -15,13 +17,18 @@ export const CatalogNavigationView: FC = props => const { searchResult = null } = useCatalog(); return ( -
- { searchResult && (searchResult.filteredNodes.length > 0) && searchResult.filteredNodes.map((n, index) => - { - return ; - }) } - { !searchResult && - } -
+ <> + + + + { searchResult && (searchResult.filteredNodes.length > 0) && searchResult.filteredNodes.map((n, index) => + { + return ; + }) } + { !searchResult && + } + + + ); }; diff --git a/src/components/catalog/views/page/common/CatalogGridOfferView.tsx b/src/components/catalog/views/page/common/CatalogGridOfferView.tsx index a3fcedd..f99bbad 100644 --- a/src/components/catalog/views/page/common/CatalogGridOfferView.tsx +++ b/src/components/catalog/views/page/common/CatalogGridOfferView.tsx @@ -1,9 +1,8 @@ import { MouseEventType } from '@nitrots/nitro-renderer'; import { FC, MouseEvent, useMemo, useState } from 'react'; -import { FaHeart } from 'react-icons/fa'; import { IPurchasableOffer, Offer, ProductTypeEnum } from '../../../../../api'; import { LayoutAvatarImageView, LayoutGridItem, LayoutGridItemProps } from '../../../../../common'; -import { useCatalog, useCatalogFavorites, useInventoryFurni } from '../../../../../hooks'; +import { useCatalog, useInventoryFurni } from '../../../../../hooks'; interface CatalogGridOfferViewProps extends LayoutGridItemProps { @@ -17,8 +16,6 @@ export const CatalogGridOfferView: FC = props => const [ isMouseDown, setMouseDown ] = useState(false); const { requestOfferToMover = null } = useCatalog(); const { isVisible = false } = useInventoryFurni(); - const { isFavoriteOffer, toggleFavoriteOffer } = useCatalogFavorites(); - const isFav = isFavoriteOffer(offer.offerId); const iconUrl = useMemo(() => { @@ -54,28 +51,9 @@ export const CatalogGridOfferView: FC = props => if(!product) return null; return ( - + { (offer.product.productType === ProductTypeEnum.ROBOT) && } -
{ e.stopPropagation(); e.preventDefault(); toggleFavoriteOffer(offer.offerId, offer.localizationName, iconUrl); } } - onMouseDown={ e => e.stopPropagation() } - > - -
); }; diff --git a/src/components/catalog/views/page/common/CatalogSearchView.tsx b/src/components/catalog/views/page/common/CatalogSearchView.tsx index 7cc30c7..dc3f34b 100644 --- a/src/components/catalog/views/page/common/CatalogSearchView.tsx +++ b/src/components/catalog/views/page/common/CatalogSearchView.tsx @@ -2,9 +2,11 @@ import { GetSessionDataManager, IFurnitureData } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { FaSearch, FaTimes } from 'react-icons/fa'; import { CatalogPage, CatalogType, FilterCatalogNode, FurnitureOffer, GetOfferNodes, ICatalogNode, ICatalogPage, IPurchasableOffer, LocalizeText, PageLocalization, SearchResult } from '../../../../../api'; +import { Button, Flex } from '../../../../../common'; import { useCatalog } from '../../../../../hooks'; +import { NitroInput } from '../../../../../layout'; -export const CatalogSearchView: FC<{}> = () => +export const CatalogSearchView: FC<{}> = props => { const [ searchValue, setSearchValue ] = useState(''); const { currentType = null, rootNode = null, offersToNodes = null, searchResult = null, setSearchResult = null, setCurrentPage = null } = useCatalog(); @@ -76,22 +78,29 @@ export const CatalogSearchView: FC<{}> = () => }, [ offersToNodes, currentType, rootNode, searchValue, setCurrentPage, setSearchResult ]); return ( -
- - setSearchValue(e.target.value) } - /> - { searchValue && searchValue.length > 0 && - } +
+ + + + + + + + setSearchValue(event.target.value) } /> + + + + { (!searchValue || !searchValue.length) && + } + { searchValue && !!searchValue.length && + }
); }; diff --git a/src/components/catalog/views/page/layout/CatalogLayoutCustomPrefixView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutCustomPrefixView.tsx index 65f9a21..0b7f904 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutCustomPrefixView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutCustomPrefixView.tsx @@ -1,6 +1,7 @@ import { PurchasePrefixComposer } from '@nitrots/nitro-renderer'; +import { createPortal } from 'react-dom'; import { FC, useEffect, useMemo, useRef, useState } from 'react'; -import { LocalizeText, SendMessageComposer, PRESET_PREFIX_EFFECTS, parsePrefixColors, getPrefixEffectStyle, PREFIX_EFFECT_KEYFRAMES } from '../../../../../api'; +import { SendMessageComposer, PRESET_PREFIX_EFFECTS, parsePrefixColors, getPrefixEffectStyle, PREFIX_EFFECT_KEYFRAMES } from '../../../../../api'; import { CatalogLayoutProps } from './CatalogLayout.types'; import data from '@emoji-mart/data'; import Picker from '@emoji-mart/react'; @@ -31,6 +32,32 @@ export const CatalogLayoutCustomPrefixView: FC = props => const [ showIconPicker, setShowIconPicker ] = useState(false); const [ selectedEffect, setSelectedEffect ] = useState(''); const [ purchased, setPurchased ] = useState(false); + const pickerContainerRef = useRef(null); + + // Inject style into emoji-mart Shadow DOM to remove backdrop-filter blur + useEffect(() => + { + if(!showIconPicker) return; + + const timer = setTimeout(() => + { + const container = pickerContainerRef.current; + if(!container) return; + + const emPicker = container.querySelector('em-emoji-picker'); + if(!emPicker?.shadowRoot) return; + + const existing = emPicker.shadowRoot.querySelector('#no-blur-fix'); + if(existing) return; + + const style = document.createElement('style'); + style.id = 'no-blur-fix'; + style.textContent = `.sticky { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; background-color: rgb(var(--em-rgb-background)) !important; } .menu { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; background-color: rgb(var(--em-rgb-background)) !important; }`; + emPicker.shadowRoot.appendChild(style); + }, 50); + + return () => clearTimeout(timer); + }, [ showIconPicker ]); const colorString = useMemo(() => { @@ -77,7 +104,7 @@ export const CatalogLayoutCustomPrefixView: FC = props => setLetterColors(prev => ({ ...prev, [selectedLetterIndex]: color })); setCustomColorInput(color); - // Auto-avanza alla lettera successiva + // Auto-advance to next letter if(selectedLetterIndex < prefixText.length - 1) { const nextIdx = selectedLetterIndex + 1; @@ -167,12 +194,12 @@ export const CatalogLayoutCustomPrefixView: FC = props => { /* Text + Icon Row */ }
- +
= props =>
- +
@@ -214,14 +241,14 @@ export const CatalogLayoutCustomPrefixView: FC = props =>
- { /* Emoji Picker (emoji-mart) - fixed overlay */ } - { showIconPicker && ( + { /* Emoji Picker (emoji-mart) - portaled to body, no backdrop */ } + { showIconPicker && createPortal( <> -
setShowIconPicker(false) } /> -
+
setShowIconPicker(false) } /> +
{ setSelectedIcon(emoji.native); setShowIconPicker(false); } } theme="dark" previewPosition="none" @@ -234,12 +261,13 @@ export const CatalogLayoutCustomPrefixView: FC = props => set="native" />
- + , + document.body ) } { /* Effect Selector */ }
- +
{ PRESET_PREFIX_EFFECTS.map(fx => (
@@ -288,7 +316,7 @@ export const CatalogLayoutCustomPrefixView: FC = props =>
- { LocalizeText('catalog.prefix.color.hint') } + Select a letter, then choose a color. Auto-advances.
= props =>
{ colorMode === 'perLetter' && selectedLetterIndex !== null && - { LocalizeText('catalog.prefix.color.selected') } "{ prefixText[selectedLetterIndex] || '' }" + Selected letter: "{ prefixText[selectedLetterIndex] || '' }" } -
+
{ PRESET_COLORS.map((color, idx) => { const isActive = currentActiveColor === color; return (
handleColorSelect(color) } /> @@ -410,8 +443,8 @@ export const CatalogLayoutCustomPrefixView: FC = props =>
- { LocalizeText('catalog.prefix.price') } - { LocalizeText('catalog.prefix.price.amount') } + Price: + 5 Credits
diff --git a/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx index 107b820..50b2955 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx @@ -1,9 +1,7 @@ import { FC } from 'react'; -import { FaEdit, FaPlus } from 'react-icons/fa'; -import { GetConfigurationValue, LocalizeText, ProductTypeEnum } from '../../../../../api'; -import { Text } from '../../../../../common'; +import { GetConfigurationValue, ProductTypeEnum } from '../../../../../api'; +import { Column, Flex, Grid, LayoutImage, Text } from '../../../../../common'; import { useCatalog } from '../../../../../hooks'; -import { useCatalogAdmin } from '../../../CatalogAdminContext'; import { CatalogHeaderView } from '../../catalog-header/CatalogHeaderView'; import { CatalogAddOnBadgeWidgetView } from '../widgets/CatalogAddOnBadgeWidgetView'; import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView'; @@ -18,87 +16,46 @@ export const CatalogLayoutDefaultView: FC = props => { const { page = null } = props; const { currentOffer = null, currentPage = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const adminMode = catalogAdmin?.adminMode ?? false; return ( -
- { /* Admin: quick actions */ } - { adminMode && !catalogAdmin.editingPageData && -
- - -
} - - { /* Product detail card */ } - { currentOffer && -
- { /* Preview area */ } -
- { (currentOffer.product.productType !== ProductTypeEnum.BADGE) && - <> - - - } - { (currentOffer.product.productType === ProductTypeEnum.BADGE) && - } -
- { /* Product info + purchase */ } -
- { /* Title row */ } -
-
- { currentOffer.localizationName } - { adminMode && - catalogAdmin.setEditingOffer(currentOffer) } - /> } -
- { adminMode && -
- ID: { currentOffer.product.productClassId } - Offer: { currentOffer.offerId } - { currentOffer.product.productType.toUpperCase() } -
} - -
- { /* Price */ } - - { /* Spinner */ } - - { /* Actions */ } -
- -
-
-
} - - { /* Welcome/description card */ } - { !currentOffer && -
- { !!page.localization.getImage(1) && - } - -
} - - { /* Item grid */ } -
- { GetConfigurationValue('catalog.headers') && - } - -
-
+ <> + + + { GetConfigurationValue('catalog.headers') && + } + + + + { !currentOffer && + <> + { !!page.localization.getImage(1) && + } + + } + { currentOffer && + <> + + { (currentOffer.product.productType !== ProductTypeEnum.BADGE) && + <> + + + } + { (currentOffer.product.productType === ProductTypeEnum.BADGE) && } + + + + { currentOffer.localizationName } +
+
+ +
+ +
+ +
+ } +
+
+ ); }; diff --git a/src/components/catalog/views/page/layout/CatalogLayoutPets3View.tsx b/src/components/catalog/views/page/layout/CatalogLayoutPets3View.tsx index caba81a..8c2e085 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutPets3View.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutPets3View.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { FaPaw } from 'react-icons/fa'; +import { Column } from '../../../../../common'; import { CatalogLayoutProps } from './CatalogLayout.types'; export const CatalogLayoutPets3View: FC = props => @@ -9,28 +9,17 @@ export const CatalogLayoutPets3View: FC = props => const imageUrl = page.localization.getImage(1); return ( -
- { /* Header card */ } -
- { imageUrl && } -
-
- - -
-
+ +
+ { imageUrl && } +
- - { /* Content */ } -
-
+ +
+ +
+
- - { /* Footer */ } - { !!page.localization.getText(3) && -
- -
} -
+ ); }; diff --git a/src/components/catalog/views/page/layout/CatalogLayoutTrophiesView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutTrophiesView.tsx index d192b81..bcea3d6 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutTrophiesView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutTrophiesView.tsx @@ -1,10 +1,6 @@ import { FC, useEffect, useState } from 'react'; -import { FaEdit, FaPen, FaPlus, FaTrophy } from 'react-icons/fa'; -import { LocalizeText, ProductTypeEnum } from '../../../../../api'; -import { Text } from '../../../../../common'; +import { Column, Grid, Text } from '../../../../../common'; import { useCatalog } from '../../../../../hooks'; -import { useCatalogAdmin } from '../../../CatalogAdminContext'; -import { CatalogAddOnBadgeWidgetView } from '../widgets/CatalogAddOnBadgeWidgetView'; import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView'; import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView'; import { CatalogTotalPriceWidget } from '../widgets/CatalogTotalPriceWidget'; @@ -16,8 +12,6 @@ export const CatalogLayoutTrophiesView: FC = props => const { page = null } = props; const [ trophyText, setTrophyText ] = useState(''); const { currentOffer = null, setPurchaseOptions = null } = useCatalog(); - const catalogAdmin = useCatalogAdmin(); - const adminMode = catalogAdmin?.adminMode ?? false; useEffect(() => { @@ -33,104 +27,30 @@ export const CatalogLayoutTrophiesView: FC = props => }); }, [ currentOffer, trophyText, setPurchaseOptions ]); - const canPurchase = currentOffer && trophyText.trim().length > 0; - return ( -
- { /* Admin: quick actions */ } - { adminMode && !catalogAdmin.editingPageData && -
- - -
} - - { /* Selected trophy card */ } - { currentOffer - ?
- { /* Preview */ } -
- { (currentOffer.product.productType !== ProductTypeEnum.BADGE) - ? <> - - - - : } -
- { /* Info */ } -
-
- - { currentOffer.localizationName } - { adminMode && - catalogAdmin.setEditingOffer(currentOffer) } - /> } -
- { adminMode && -
- ID: { currentOffer.product.productClassId } - Offer: { currentOffer.offerId } -
} - - { !canPurchase && - { LocalizeText('catalog.trophies.write.hint') } } -
+ + + +