diff --git a/apps/frontend/components/auctions/AuctionsSidebar.svelte b/apps/frontend/components/auctions/AuctionsSidebar.svelte index a12fd2550..da9cf2cf4 100644 --- a/apps/frontend/components/auctions/AuctionsSidebar.svelte +++ b/apps/frontend/components/auctions/AuctionsSidebar.svelte @@ -65,6 +65,10 @@ name: 'Commodities', slug: 'commodities', }, + { + name: 'Recipes', + slug: 'recipes', + }, { name: 'Extra Pets', slug: 'extra-pets', diff --git a/apps/frontend/components/auctions/AuctionsView.svelte b/apps/frontend/components/auctions/AuctionsView.svelte index 89975c47b..bc6a4fbf5 100644 --- a/apps/frontend/components/auctions/AuctionsView.svelte +++ b/apps/frontend/components/auctions/AuctionsView.svelte @@ -21,6 +21,7 @@ import Missing from './AuctionsMissing.svelte'; import MissingBigResults from './AuctionsMissingBigResults.svelte'; import RadioGroup from '@/shared/components/forms/RadioGroup.svelte'; + import Recipes from './recipes/Recipes.svelte'; import Select from '@/shared/components/forms/Select.svelte'; import SpecificItem from './AuctionsSpecificItem.svelte'; import TextInput from '@/shared/components/forms/TextInput.svelte'; @@ -87,6 +88,7 @@ 'missing-recipes': MissingBigResults, 'sell-commodities': Commodities, 'sell-extra-pets': ExtraPets, + 'sell-recipes': Recipes, 'specific-item': SpecificItem, }; diff --git a/apps/frontend/components/auctions/commodities/store.ts b/apps/frontend/components/auctions/commodities/store.ts index d83898a02..e2d6fa87e 100644 --- a/apps/frontend/components/auctions/commodities/store.ts +++ b/apps/frontend/components/auctions/commodities/store.ts @@ -6,8 +6,7 @@ export class CommodityAuctionsStore { private static url = '/api/auctions/commodities'; private cache: CommodityData = null; - async fetch() // auctionState: AuctionState - : Promise { + async fetch(): Promise { let ret: CommodityData; if (this.cache !== null) { diff --git a/apps/frontend/components/auctions/recipes/Item.svelte b/apps/frontend/components/auctions/recipes/Item.svelte new file mode 100644 index 000000000..1d6e5e781 --- /dev/null +++ b/apps/frontend/components/auctions/recipes/Item.svelte @@ -0,0 +1,39 @@ + + + + + + + + + + + {#each auctions as auction} + + + + + {/each} + +
+ + + + + {totalCount} +
{connectedRealmName(auction.connectedRealmId)}{Math.floor(auction.buyoutPrice / 10_000).toLocaleString()} g
diff --git a/apps/frontend/components/auctions/recipes/Recipes.svelte b/apps/frontend/components/auctions/recipes/Recipes.svelte new file mode 100644 index 000000000..5dadd9c69 --- /dev/null +++ b/apps/frontend/components/auctions/recipes/Recipes.svelte @@ -0,0 +1,42 @@ + + +{#await recipesAuctionStore.fetch()} + MOO +{:then auctions} + {@const haveData = processAuctions(auctions)} + {#each haveData as [itemId, auctions, haveItems]} + + {/each} +{/await} diff --git a/apps/frontend/components/auctions/recipes/store.ts b/apps/frontend/components/auctions/recipes/store.ts new file mode 100644 index 000000000..d84edeb52 --- /dev/null +++ b/apps/frontend/components/auctions/recipes/store.ts @@ -0,0 +1,58 @@ +import { + UserAuctionDataAuction, + type UserAuctionDataAuctionArray, +} from '@/types/data/user-auctions'; +import { getNumberKeyedEntries } from '@/utils/get-number-keyed-entries'; + +export type RecipesData = Record>; +type RecipesResponse = Record< + number, + { + rawAuctions: Record; + } +>; + +export class RecipesAuctionsStore { + private static url = '/api/auctions/recipes'; + private cache: RecipesData = null; + + async fetch(): Promise { + let ret: RecipesData; + + if (this.cache !== null) { + ret = this.cache; + } else { + const xsrf = document.getElementById('app').getAttribute('data-xsrf'); + + const response = await fetch(RecipesAuctionsStore.url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + RequestVerificationToken: xsrf, + }, + }); + + ret = {}; + if (response.ok) { + const responseData = (await response.json()) as RecipesResponse; + + for (const [region, itemAuctions] of getNumberKeyedEntries(responseData)) { + ret[region] = {}; + + for (const [itemId, rawAuctions] of getNumberKeyedEntries( + itemAuctions.rawAuctions + )) { + ret[region][itemId] = rawAuctions.map( + (auctionArray) => new UserAuctionDataAuction(...auctionArray) + ); + } + } + } + + this.cache = ret; + } + + return ret; + } +} +export const recipesAuctionStore = new RecipesAuctionsStore(); diff --git a/apps/frontend/data/achievements.ts b/apps/frontend/data/achievements.ts index b5659ef72..0779698fb 100644 --- a/apps/frontend/data/achievements.ts +++ b/apps/frontend/data/achievements.ts @@ -441,6 +441,29 @@ export const extraCategories: ExtraAchievementCategory[] = [ 41597, // Glory of the Omega Raider ], }, + { + targetSlug: 'player-vs-player/world', + nameType: 1, + onlyAchievementIds: true, + achievementIds: [ + 40087, // Unbound Battle + 40097, // Ruffious's Bid + 40088, // A Champion's Tour: The War Within + 40086, // Tour of Duty: Azj-Kahet + 40085, // Tour of Duty: Hallowfall + 40084, // Tour of Duty: The Ringing Deeps + 40083, // Tour of Duty: Isle of Dorn + 40089, // Spoiled Goods 1 + 40090, // Spoiled Goods 2 + 40091, // Slightly Spoiled + 41522, // Tour of Duty: Undermine + 42131, // Tour of Duty: K'aresh + 40468, // Unbound Glory 1 + 40466, // Unbound Glory 2 + 40467, // Unbound Glory 3 + 40465, // Unbound Bounty + ], + }, null, { targetSlug: 'expansion-features/skyriding', @@ -483,14 +506,28 @@ export const extraCategories: ExtraAchievementCategory[] = [ { targetSlug: 'delves/midnight', nameType: 1, - achievementIds: [], + achievementIds: [ + 63718, // Lock and Key + 63719, // Lock and Key Master + 63720, // Happy Hexmask Collector + 63721, // The Labyrinth of Kindo'jan + 63722, // Whose Labyrinth? + 63723, // My Labyrinth + 63724, // Knock Knock + 63717, // Kindo'jan's Labyrinth Discoveries + 63727, // Treasures Upon Treasures + 63728, // A Few More Can't Hurt + ], }, { targetSlug: 'dungeons-raids/midnight-dungeon', nameType: 3, overrideName: 'Dungeons', overrideSlug: 'dungeons', - achievementIds: [61567, 61568], + achievementIds: [ + 61567, // Midnight Dungeon Hero + 61568, // Glory of the Midnight Hero + ], }, { targetSlug: 'dungeons-raids/midnight-raid', @@ -499,6 +536,7 @@ export const extraCategories: ExtraAchievementCategory[] = [ overrideSlug: 'raids', achievementIds: [ 61380, // Glory of the Midnight Raider + 63254, // Glory of the Venomous Raider ], }, { diff --git a/apps/frontend/data/currencies.ts b/apps/frontend/data/currencies.ts index 070bc7564..a2875262a 100644 --- a/apps/frontend/data/currencies.ts +++ b/apps/frontend/data/currencies.ts @@ -218,7 +218,7 @@ export const currencyExtra: Record = { 3028, // Restored Coffer Key 2803, // Undercoin 3356, // Untainted Mana-Crystals - 3513, // Nebulous Voidcore (new?) + 3418, // Nebulous Voidcore null, 3442, // Adventurer Mistcrest 3443, // Veteran Mistcrest diff --git a/apps/frontend/user-home/components/reputations/AccountWide.svelte b/apps/frontend/user-home/components/reputations/AccountWide.svelte index 824bbcd76..3bd6a6f00 100644 --- a/apps/frontend/user-home/components/reputations/AccountWide.svelte +++ b/apps/frontend/user-home/components/reputations/AccountWide.svelte @@ -87,6 +87,12 @@ reputationSetsIndex, slug, })} + {@const repId = + reputationSet.both?.id || reputationSet.alliance?.id || reputationSet.horde?.id} + {@const repIcon = + reputationSet.both?.icon || + reputationSet.alliance?.icon || + reputationSet.horde?.icon}