Cleanup random API and create named action for a random search.

This commit is contained in:
Bradley Shellnut 2022-12-26 23:15:41 -08:00
parent 3f9759aef1
commit 391fba7955
5 changed files with 113 additions and 212 deletions

View file

@ -5,30 +5,12 @@
import { ToastType } from '$root/lib/types'; import { ToastType } from '$root/lib/types';
import { toast } from '../../toast/toast'; import { toast } from '../../toast/toast';
// async function handleSubmit(event: SubmitEvent) {
// // submitting = true;
// boredState.update((n) => ({ ...n, loading: true }));
// const form = event.target as HTMLFormElement;
// console.log('form', form);
// const response = await fetch('/api/games', {
// method: 'POST',
// headers: { accept: 'application/json' },
// body: new FormData(form)
// });
// const responseData = await response.json();
// // submitting = false;
// boredState.update((n) => ({ ...n, loading: false }));
// gameStore.removeAll();
// gameStore.addAll(responseData?.games);
// // games = responseData?.games;
// }
let submitting = $boredState?.loading; let submitting = $boredState?.loading;
let checked = true; let checked = true;
</script> </script>
<form <form
action="/search" action="/search?/random"
method="POST" method="POST"
use:enhance={() => { use:enhance={() => {
gameStore.removeAll(); gameStore.removeAll();
@ -58,7 +40,7 @@
}} }}
> >
<fieldset aria-busy={submitting} disabled={submitting}> <fieldset aria-busy={submitting} disabled={submitting}>
<input type="checkbox" id="random" name="random" hidden {checked} /> <!-- <input type="checkbox" id="random" name="random" hidden {checked} /> -->
<button class="btn" type="submit" disabled={submitting}>Random Game 🎲</button> <button class="btn" type="submit" disabled={submitting}>Random Game 🎲</button>
</fieldset> </fieldset>
</form> </form>

View file

@ -1,125 +1,125 @@
import type { SvelteComponent } from "svelte"; import type { SvelteComponent } from 'svelte';
export type Dialog = { export type Dialog = {
isOpen: boolean; isOpen: boolean;
content?: typeof SvelteComponent; content?: typeof SvelteComponent;
additionalData?: SavedGameType | GameType; additionalData?: SavedGameType | GameType;
} };
export type Search = { export type Search = {
name: string; name: string;
minAge: string; minAge: string;
minPlayers: string; minPlayers: string;
maxPlayers: string; maxPlayers: string;
exactMinAge: string; exactMinAge: string;
exactMinPlayers: string; exactMinPlayers: string;
exactMaxPlayers: string; exactMaxPlayers: string;
skip: number; skip: number;
currentPage: number; currentPage: number;
limit: number; limit: number;
} };
export type BoredStore = { export type BoredStore = {
loading: boolean; loading: boolean;
dialog: Dialog; dialog: Dialog;
}; };
export enum ToastType { export enum ToastType {
INFO = 'INFO', INFO = 'INFO',
ERROR = 'ERROR', ERROR = 'ERROR',
WARNING = 'WARNING' WARNING = 'WARNING'
} }
export type ToastData = { export type ToastData = {
id: number; id: number;
duration: number; duration: number;
dismissible: boolean; dismissible: boolean;
showButton: boolean; showButton: boolean;
autoDismiss: boolean; autoDismiss: boolean;
type: ToastType; type: ToastType;
message: string; message: string;
}; };
export type SavedGameType = { export type SavedGameType = {
id: string; id: string;
name: string; name: string;
thumb_url: string; thumb_url: string;
players: string; players: string;
playtime: string; playtime: string;
} };
export type GameType = { export type GameType = {
id: string; id: string;
handle: string; handle: string;
name: string; name: string;
url: string; url: string;
edit_url: string; edit_url: string;
thumb_url: string; thumb_url: string;
image_url: string; image_url: string;
price: number; price: number;
price_ca: number; price_ca: number;
price_uk: number; price_uk: number;
price_au: number; price_au: number;
msrp: number; msrp: number;
year_published: number; year_published: number;
min_players: number; min_players: number;
max_players: number; max_players: number;
min_playtime: number; min_playtime: number;
max_playtime: number; max_playtime: number;
min_age: number; min_age: number;
description: string; description: string;
description_preview: string; description_preview: string;
players: string; players: string;
playtime: string; playtime: string;
}; };
export type SearchQuery = { export type SearchQuery = {
client_id: string; client_id: string;
limit?: number; limit?: number;
skip?: number; skip?: number;
ids?: string[]; ids?: string[];
list_id?: string; list_id?: string;
kickstarter?: boolean; kickstarter?: boolean;
random?: boolean; random?: boolean;
name?: string; name?: string;
exact?: boolean; exact?: boolean;
fuzzy_match?: boolean; fuzzy_match?: boolean;
designer?: string; designer?: string;
publisher?: string; publisher?: string;
artist?: string; artist?: string;
mechanics?: string; mechanics?: string;
categories?: string; categories?: string;
order_by?: string; order_by?: string;
ascending?: boolean; ascending?: boolean;
min_players?: number; min_players?: number;
max_players?: number; max_players?: number;
min_playtime?: number; min_playtime?: number;
max_playtime?: number; max_playtime?: number;
min_age?: number; min_age?: number;
year_published?: number; year_published?: number;
gt_min_players?: number; gt_min_players?: number;
gt_max_players?: number; gt_max_players?: number;
gt_min_playtime?: number; gt_min_playtime?: number;
gt_max_playtime?: number; gt_max_playtime?: number;
gt_min_age?: number; gt_min_age?: number;
gt_year_published?: number; gt_year_published?: number;
gt_price?: bigint; gt_price?: bigint;
gt_msrp?: bigint; gt_msrp?: bigint;
gt_discount?: bigint; gt_discount?: bigint;
gt_reddit_count?: number; gt_reddit_count?: number;
gt_reddit_week_count?: number; gt_reddit_week_count?: number;
gt_reddit_day_count?: number; gt_reddit_day_count?: number;
lt_min_players?: number; lt_min_players?: number;
lt_max_players?: number; lt_max_players?: number;
lt_min_playtime?: number; lt_min_playtime?: number;
lt_max_playtime?: number; lt_max_playtime?: number;
lt_min_age?: number; lt_min_age?: number;
lt_year_published?: number; lt_year_published?: number;
lt_price?: bigint; lt_price?: bigint;
lt_msrp?: bigint; lt_msrp?: bigint;
lt_discount?: bigint; lt_discount?: bigint;
lt_reddit_count?: number; lt_reddit_count?: number;
lt_reddit_week_count?: number; lt_reddit_week_count?: number;
lt_reddit_day_count?: number; lt_reddit_day_count?: number;
fields?: string; fields?: string;
}; };

View file

@ -2,13 +2,7 @@ import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { boardGameApi } from '../../api'; import { boardGameApi } from '../../api';
type GamePageParams = { export const load: PageServerLoad = async ({ params, setHeaders }) => {
params: {
id: string;
};
};
export const load: PageServerLoad = async ({ params, setHeaders }: GamePageParams) => {
const queryParams = { const queryParams = {
ids: `${params?.id}` ids: `${params?.id}`
}; };

View file

@ -225,6 +225,7 @@
place-items: center; place-items: center;
gap: 1.5rem; gap: 1.5rem;
margin: 1rem; margin: 1rem;
line-height: 1.5em;
} }
.overflow-description { .overflow-description {

View file

@ -1,7 +1,7 @@
import type { Actions, PageServerLoad, RequestEvent } from '../$types'; import type { Actions, PageServerLoad, RequestEvent } from '../$types';
import { BOARD_GAME_ATLAS_CLIENT_ID } from '$env/static/private'; import { BOARD_GAME_ATLAS_CLIENT_ID } from '$env/static/private';
import { error, fail } from '@sveltejs/kit'; import { error, fail } from '@sveltejs/kit';
import type { GameType, Search, SearchQuery } from '$root/lib/types'; import type { GameType, RandomSearch, Search, SearchQuery } from '$root/lib/types';
import { mapAPIGameToBoredGame } from '$root/lib/util/gameMapper'; import { mapAPIGameToBoredGame } from '$root/lib/util/gameMapper';
import { search_schema } from '$root/lib/zodValidation'; import { search_schema } from '$root/lib/zodValidation';
import { ZodError } from 'zod'; import { ZodError } from 'zod';
@ -144,90 +144,20 @@ export const load: PageServerLoad = async ({ fetch, url }) => {
}; };
export const actions: Actions = { export const actions: Actions = {
default: async ({ request }: RequestEvent): Promise<any> => { random: async ({ request }: RequestEvent): Promise<any> => {
console.log('In search action specific');
// Do things in here
const formData = Object.fromEntries(await request.formData()) as Search;
console.log('formData', formData);
console.log('passed in limit:', formData?.limit);
console.log('passed in skip:', formData?.skip);
const limit = formData?.limit || 10;
const skip = formData?.skip || 0;
const queryParams: SearchQuery = { const queryParams: SearchQuery = {
order_by: 'rank', order_by: 'rank',
ascending: false, ascending: false,
limit: +limit,
skip: +skip,
client_id: BOARD_GAME_ATLAS_CLIENT_ID, client_id: BOARD_GAME_ATLAS_CLIENT_ID,
fuzzy_match: true, random: true
name: ''
}; };
// TODO: Check name length and not search if not advanced search
const random = formData?.random === 'on';
if (random) {
console.log('Random');
queryParams.random = random;
} else {
try {
const {
name,
minAge,
minPlayers,
maxPlayers,
exactMinAge,
exactMinPlayers,
exactMaxPlayers
} = search_schema.parse(formData);
if (minAge) {
if (exactMinAge) {
queryParams.min_age = minAge;
} else {
queryParams.gt_min_age = minAge === 1 ? 0 : minAge - 1;
}
}
if (minPlayers) {
if (exactMinPlayers) {
queryParams.min_players = minPlayers;
} else {
queryParams.gt_min_players = minPlayers === 1 ? 0 : minPlayers - 1;
}
}
if (maxPlayers) {
if (exactMaxPlayers) {
queryParams.max_players = maxPlayers;
} else {
queryParams.lt_max_players = maxPlayers + 1;
}
}
if (name) {
queryParams.name = name;
}
} catch (error: unknown) {
if (error instanceof ZodError) {
console.log(error);
const { fieldErrors: errors } = error.flatten();
return fail(400, { data: formData, errors });
}
}
}
const newQueryParams: Record<string, string> = {}; const newQueryParams: Record<string, string> = {};
for (const key in queryParams) { for (const key in queryParams) {
console.log('key', key);
console.log('queryParams[key]', queryParams[key as keyof SearchQuery]);
newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`; newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`;
} }
const urlQueryParams = new URLSearchParams(newQueryParams); const urlQueryParams = new URLSearchParams(newQueryParams);
console.log('urlQueryParams', urlQueryParams);
try { try {
const url = `https://api.boardgameatlas.com/api/search${ const url = `https://api.boardgameatlas.com/api/search${
@ -260,20 +190,14 @@ export const actions: Actions = {
// console.log('returning from search', games) // console.log('returning from search', games)
return { return {
games, games
totalCount,
limit: parseInt(limit),
skip: parseInt(skip)
}; };
} }
} catch (e) { } catch (e) {
console.log(`Error searching board games ${e}`); console.log(`Error searching board games ${e}`);
} }
return { return {
games: [], games: []
totalCount: 0,
limit,
skip
}; };
} }
}; };