Commit Graph

13 Commits

Author SHA1 Message Date
simoleo89 2a5b9a4a98 useClubOffers: per-windowId TanStack query for HC offer pages
Two catalog layouts each fire 'new GetClubOffersMessageComposer(windowId)'
on mount and read parser.offers via HabboClubOffersMessageEvent:

  - CatalogLayoutVipBuyView (windowId 1)
  - CatalogLayoutBuildersClubBuyView (windowId 2 / 3, depending on
    the addon variant)

Plus useCatalog used to also listen for HabboClubOffersMessageEvent and
stash the offers in 'catalogOptions.clubOffersByWindowId[windowId]' and
'catalogOptions.clubOffers' (the latter being a backward-compat alias
for windowId 1). Three listeners, three independent requests when all
mounted.

New useClubOffers(windowId) wraps the request/response pair as a
TanStack query keyed by '['nitro', 'catalog', 'clubOffers', windowId]'.
accept(): correlation-key filter (parser.windowId === windowId) so
the same multiplexed event doesn't satisfy the wrong query slot.

Both layouts now read 'const { data: offers = null } = useClubOffers(windowId)';
useCatalog drops the listener, ICatalogOptions drops the
clubOffers / clubOffersByWindowId fields and HabboClubOffersMessageEvent
no longer needs to be imported in useCatalog. The localization-refresh
effect that re-cloned both fields is also dropped — React Query owns
the cache now, and ClubOfferData has no localized strings anyway.
2026-05-11 22:23:19 +02:00
simoleo89 2d9785e931 useUserGroups: consolidate 4 dedup'd CatalogGroupsComposer call sites
Four independent components used to send 'new CatalogGroupsComposer()'
on mount and listen for GuildMembershipsMessageEvent:

  - useCatalog (writing into catalogOptions.groups)
  - CatalogLayoutGuildForumView
  - CatalogGuildSelectorWidgetView
  - WiredSelectorUsersGroupView
  - WiredConditionActorIsGroupMemberView

Each fired its own request and re-listened independently. With four
of them mounted in the wired-tools panel during a builder session,
the same packet went out four times.

New useUserGroups() hook wraps the request/response pair with
useNitroQuery (queryKey ['nitro', 'user', 'groups'], staleTime
Infinity — guild membership is session-stable). All four consumers
now read 'const { data: groups = [] } = useUserGroups()' and React
Query dedups: one composer at the first mount, all subsequent mounts
get the cached array.

Drops 'groups' from ICatalogOptions and the corresponding listener +
prev-state-merge from useCatalog — no remaining consumer reads it.
2026-05-11 22:14:39 +02:00
simoleo89 388fb8ed34 Migrate CatalogLayoutRoomAdsView's room-ad fetch to useNitroQuery
Second concrete adoption of proposal #2 (first was OfferView).

Before
- A useState<RoomEntryData[]>([]) for availableRooms.
- A useMessageEvent<RoomAdPurchaseInfoEvent> handler that
  set the state on each parser event.
- A useEffect on mount that dispatched two composers, one of which
  was GetRoomAdPurchaseInfoComposer paired with the parser above.

After
- A single useNitroQuery call wires the request and parser as one
  read-only query. The select extracts parser.rooms with a default
  empty array.
- staleTime is 60s — opening the same panel within a minute reuses
  the cached value; the composer is not re-dispatched. Useful here
  because the user navigates between catalog tabs.
- The mount-only useEffect no longer dispatches the room-ad composer;
  the second composer (GetUserEventCatsMessageComposer) stays where
  it was — that one feeds useNavigator state and isn't a
  request-response pair this component owns.

Why this file
- It was the cleanest pattern in the catalog tree: no correlation
  keys, no conditional filter on the parser, no other writes to
  availableRooms. The pure derive-from-event case useNitroQuery is
  built for.
- The big god-hook useCatalog (1100 LOC) still owns most of the
  catalog data layer; migrating that needs the data/uiState/actions
  split first.

Verification
- yarn test: 49/49 still passing.
- yarn eslint on the touched file: 1 error (the pre-existing
  set-state-in-effect on line 36, unchanged — baseline matches).
- The previous useMessageEvent import was removed cleanly.
2026-05-11 16:40:43 +00:00
simoleo89 535fa71020 ESLint --fix: auto-fix brace-style, indent, semi, no-trailing-spaces
Run eslint --fix across src/ to clear ~1900 mechanical lint errors
surfaced by the @typescript-eslint v8 + react-hooks v7 + react-compiler
upgrade in the React 19 modernization PR.

Issues fixed automatically:
- brace-style (Allman): try/catch one-liners reformatted to multi-line
- indent: tab-vs-space and depth corrections
- semi: missing trailing semicolons
- no-trailing-spaces

No semantic changes. Remaining 701 errors are real-code issues
(set-state-in-effect, rules-of-hooks, no-unsafe-* type checks) that
need manual per-file review.

https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
2026-05-11 16:31:50 +00:00
Lorenzune 954e477e47 feat: add builders club catalog ui flow 2026-04-07 14:40:51 +02:00
DuckieTM 7ffb213ce7 ㊙️ Security Fixes
- XSS fix: Created SanitizeHtml.ts utility using DOMPurify (already in package.json but never used). Wrapped all 21 dangerouslySetInnerHTML calls in catalog views with SanitizeHtml() — only allows safe tags (b, i, u, br, span, div, p, a, strong, em, img)

- Race condition fix: Added 10-second timeout fallbacks on purchase flags in CatalogPurchaseWidgetView and CatalogGiftView so the flag auto-resets even if the server never responds
2026-03-23 22:14:03 +01:00
duckietm 33c31fe07d 🆕 Added New catalogue page 2026-03-23 15:02:20 +01:00
duckietm a0d0b5c4a4 Revert "Merge branch 'main' into furnisettingeditor-pr"
This reverts commit dfbfb1c2c1, reversing
changes made to 07702c44d0.
2026-03-23 11:49:05 +01:00
simoleo89 74dce1d55d feat(catalog): complete UI redesign with admin mode & favorites
- Modern card-based layout with vertical icon rail, breadcrumb nav, inline search
- Admin mode: edit/create/delete pages and offers, drag & drop reorder via HK API
- Favorites system: heart on furni, star on pages, localStorage persistence
- Redesigned product card with price pills, dynamic quantity spinner
- Upgraded trophies (filter tabs, parchment textarea), pets (breed/color flow),
  custom prefix (dynamic color boxes)
- Font fix: Ubuntu Regular, proper @font-face declarations
- New Tailwind design tokens and CatalogTexts.json for localization
2026-03-21 16:49:35 +01:00
simoleo89 11543bb64c feat: custom prefix system with effects, emoji picker and per-letter colors
- Catalog page for creating custom prefixes with text, per-letter colors, emoji icon and visual effects
- Emoji picker via @emoji-mart/react with createPortal + Shadow DOM blur fix
- Inventory prefix management (activate/deactivate/delete)
- Chat bubble rendering with multi-color prefix and effect support
- Prefix utilities (getPrefixEffectStyle, parsePrefixColors, PREFIX_EFFECT_KEYFRAMES)
- All UI text in English
2026-03-20 17:07:33 +01:00
duckietm bffaccf6a3 🆙 Security Fix - Will not go into details 2026-03-18 16:52:32 +01:00
duckietm f2446d232b 🆙 Upgrade to tailwind css 4.2.0 2026-02-20 08:17:17 +01:00
DuckieTM 7feb10ab15 🆙 Init V3 2026-01-31 09:10:52 +01:00