Skip to content

Commit

Permalink
can now buy items from the market
Browse files Browse the repository at this point in the history
  • Loading branch information
seiyria committed Aug 2, 2023
1 parent 6aca48e commit a19c0d5
Show file tree
Hide file tree
Showing 15 changed files with 482 additions and 246 deletions.
431 changes: 218 additions & 213 deletions client/src/app/components/modals/market/market.component.html

Large diffs are not rendered by default.

79 changes: 53 additions & 26 deletions client/src/app/components/modals/market/market.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ import {
IEquipment,
IItem,
IMarketItem,
IMarketItemExpanded,
IPagination,
IPlayer,
ItemSlot,
Rarity,
Weapon,
} from '@interfaces';
import { ModalController } from '@ionic/angular';
import { Select } from '@ngxs/store';
import { AlertController, ModalController } from '@ionic/angular';
import { Select, Store } from '@ngxs/store';
import { ContentService } from '@services/content.service';
import { MarketService } from '@services/market.service';
import { InventoryStore, PlayerStore } from '@stores';
import { InventoryStore, MarketStore, PlayerStore } from '@stores';
import { SetMarketItems } from '@stores/market/market.actions';
import { Observable } from 'rxjs';
@Component({
selector: 'app-market',
Expand All @@ -31,6 +33,10 @@ export class MarketModalComponent implements OnInit {
Record<ItemSlot, IEquipment>
>;

@Select(MarketStore.marketData) marketItems$!: Observable<
IPagination<IMarketItemExpanded>
>;

private destroyRef = inject(DestroyRef);

public readonly rarities: Rarity[] = [
Expand All @@ -53,14 +59,6 @@ export class MarketModalComponent implements OnInit {
'Resources',
];

public marketResults: IPagination<IMarketItem & { itemData: IItem }> = {
limit: 25,
page: 0,
lastPage: 0,
results: [],
total: 0,
};

public searchRarities: Record<string, boolean> = {};
public searchTypes: Record<string, boolean> = {};

Expand All @@ -70,6 +68,8 @@ export class MarketModalComponent implements OnInit {
public searchCostMin = 0;
public searchCostMax = 0;

public searchPage = 0;

public loading = false;

public player!: IPlayer;
Expand All @@ -80,7 +80,9 @@ export class MarketModalComponent implements OnInit {
}

constructor(
private store: Store,
private modalCtrl: ModalController,
private alertCtrl: AlertController,
private contentService: ContentService,
private marketService: MarketService,
) {}
Expand Down Expand Up @@ -113,14 +115,12 @@ export class MarketModalComponent implements OnInit {
this.searchTypes[type] = !this.searchTypes[type];
}

public myListings() {}

public isEquippableItemType(item: IItem) {
return item.type !== 'collectible' && item.type !== 'resource';
}

public changePage(newPage: number) {
this.marketResults.page = newPage;
this.searchPage = newPage;

this.search();
}
Expand All @@ -130,7 +130,7 @@ export class MarketModalComponent implements OnInit {

this.marketService
.getItems({
page: this.marketResults.page,
page: this.searchPage,
name: this.searchName,
levelMin: this.searchLevelMin,
levelMax: this.searchLevelMax,
Expand All @@ -142,15 +142,19 @@ export class MarketModalComponent implements OnInit {
types: Object.keys(this.searchTypes).filter((t) => this.searchTypes[t]),
})
.subscribe((results) => {
const itemResults = results.results.map((item) => ({
...item,
itemData: this.contentService.getItem(item.itemId)!,
}));

this.marketResults = {
...results,
results: itemResults,
};
const itemResults = (results.results as IMarketItemExpanded[]).map(
(item) => ({
...item,
itemData: this.contentService.getItem(item.itemId)!,
}),
);

this.store.dispatch(
new SetMarketItems({
...results,
results: itemResults,
}),
);

this.loading = false;
});
Expand All @@ -168,8 +172,29 @@ export class MarketModalComponent implements OnInit {
);
}

public buyItem(listing: Partial<IMarketItem & { id: string }>) {
console.log(listing);
public async buyItem(
listing: Partial<IMarketItem & { id: string; itemData: IItem }>,
) {
const alert = await this.alertCtrl.create({
header: 'Buy Item',
message: `Are you sure you want to buy "${
listing.itemData?.name || 'this item'
}" for ${listing.price?.toLocaleString()} coins?`,
buttons: [
{
text: 'Cancel',
role: 'cancel',
},
{
text: 'Buy',
handler: async () => {
this.marketService.buyItem(listing.id!).subscribe();
},
},
],
});

await alert.present();
}

public canCompare(item: IItem) {
Expand Down Expand Up @@ -211,4 +236,6 @@ export class MarketModalComponent implements OnInit {
const currentItem = this.getEquippedItem(checkType, this.equipment);
this.compareItems(item, currentItem, () => {});
}

public myListings() {}
}
7 changes: 7 additions & 0 deletions client/src/app/services/market.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,11 @@ export class MarketService {
price,
});
}

buyItem(listingId: string) {
return this.http.post(
`${environment.apiUrl}/market/listings/${listingId}/buy`,
{},
);
}
}
1 change: 1 addition & 0 deletions client/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './achievements';
export * from './crafting';
export * from './discoveries';
export * from './inventory';
export * from './market';
export * from './ngxs';
export * from './notifications';
export * from './options';
Expand Down
6 changes: 6 additions & 0 deletions client/src/interfaces/market.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IMarketItemExpanded, IPagination } from '@interfaces';

export interface IMarketStore {
version: number;
marketData: IPagination<IMarketItemExpanded>;
}
1 change: 1 addition & 0 deletions client/src/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './achievements/achievements.store';
export * from './crafting/crafting.store';
export * from './discoveries/discoveries.store';
export * from './inventory/inventory.store';
export * from './market/market.store';
export * from './notifications/notifications.store';
export * from './options/options.store';
export * from './player/player.store';
Expand Down
11 changes: 11 additions & 0 deletions client/src/stores/market/market.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IMarketItemExpanded, IPagination } from '@interfaces';

export class SetMarketItems {
static type = '[Market] Set Items';
constructor(public marketData: IPagination<IMarketItemExpanded>) {}
}

export class RemoveMarketItem {
static type = 'RemoveMarketItem';
constructor(public listingId: string) {}
}
8 changes: 8 additions & 0 deletions client/src/stores/market/market.attachments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IAttachment } from '../../interfaces';
import { RemoveMarketItem, SetMarketItems } from './market.actions';
import { removeMarketItem, setMarketItems } from './market.functions';

export const attachments: IAttachment[] = [
{ action: SetMarketItems, handler: setMarketItems },
{ action: RemoveMarketItem, handler: removeMarketItem },
];
41 changes: 41 additions & 0 deletions client/src/stores/market/market.functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { IMarketItemExpanded, IMarketStore } from '@interfaces';
import { StateContext } from '@ngxs/store';
import { patch, removeItem } from '@ngxs/store/operators';
import { RemoveMarketItem, SetMarketItems } from './market.actions';

export const defaultStore: () => IMarketStore = () => ({
version: 0,
marketData: {
lastPage: 0,
page: 0,
results: [],
total: 0,
limit: 25,
},
});

export function setMarketItems(
ctx: StateContext<IMarketStore>,
{ marketData }: SetMarketItems,
) {
ctx.setState(
patch({
marketData,
}),
);
}

export function removeMarketItem(
ctx: StateContext<IMarketStore>,
{ listingId }: RemoveMarketItem,
) {
ctx.setState(
patch({
marketData: patch({
results: removeItem<IMarketItemExpanded>(
(item) => item.id === listingId,
),
}),
}),
);
}
11 changes: 11 additions & 0 deletions client/src/stores/market/market.migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IMarketStore } from '@interfaces';

export const marketStoreMigrations = [
{
version: 0,
migrate: (state: IMarketStore) => ({
...state,
version: 1,
}),
},
].map((x) => ({ ...x, key: 'market' }));
30 changes: 30 additions & 0 deletions client/src/stores/market/market.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import { Selector, State } from '@ngxs/store';
import { attachAction } from '@seiyria/ngxs-attach-action';

import { IMarketStore } from '@interfaces';
import { defaultStore } from './market.functions';

import { getStateHelpers } from '@helpers/store-context';
import { attachments } from './market.attachments';

@State<IMarketStore>({
name: 'market',
defaults: defaultStore(),
})
@Injectable()
export class MarketStore {
constructor() {
const helpers = getStateHelpers();
attachments.forEach(({ action, handler }) => {
attachAction(MarketStore, action, (ctx, action) => {
handler(ctx, action, helpers);
});
});
}

@Selector()
static marketData(state: IMarketStore) {
return state.marketData;
}
}
1 change: 1 addition & 0 deletions client/src/stores/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './achievements/achievements.migrations';
export * from './crafting/crafting.migrations';
export * from './discoveries/discoveries.migrations';
export * from './inventory/inventory.migrations';
export * from './market/market.migrations';
export * from './notifications/notifications.migrations';
export * from './options/options.migrations';
export * from './player/player.migrations';
Expand Down
12 changes: 8 additions & 4 deletions server/src/modules/market/market.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Body,
Controller,
Get,
Param,
Patch,
Post,
Put,
Expand Down Expand Up @@ -32,8 +33,8 @@ export class MarketController {
@UseGuards(JwtAuthGuard)
@ApiOperation({ summary: 'Get the current users listings' })
@Get('listings')
async getMyListings(@User() user): Promise<IMarketItem[]> {
return [];
async getMyListings(@User() user): Promise<IPagination<IMarketItem>> {
return this.marketService.getMyListings(user.userId);
}

@UseGuards(JwtAuthGuard)
Expand Down Expand Up @@ -66,8 +67,11 @@ export class MarketController {
@UseGuards(JwtAuthGuard)
@ApiOperation({ summary: 'Buy the listing for an item' })
@Post('listings/:id/buy')
async buyListing(@User() user): Promise<Partial<IFullUser | IPatchUser>> {
return {};
async buyListing(
@User() user,
@Param('id') listingId: string,
): Promise<Partial<IFullUser | IPatchUser>> {
return this.marketService.buyItem(user.userId, listingId);
}

@UseGuards(JwtAuthGuard)
Expand Down
Loading

0 comments on commit a19c0d5

Please sign in to comment.