feat(*): Add support for catch records to My Dex page

This commit is contained in:
Josh Creek
2024-07-12 14:19:44 +01:00
parent 0e8af37309
commit e7f1930eff
6 changed files with 460 additions and 31 deletions
@@ -0,0 +1,165 @@
<script lang="ts">
import type { CatchRecord } from '$lib/models/CatchRecord';
import type { PokedexEntry } from '$lib/models/PokedexEntry';
import PokemonSprite from '../PokemonSprite.svelte';
import { createEventDispatcher } from 'svelte';
export let pokedexEntry: PokedexEntry;
export let catchRecord: CatchRecord;
const dispatch = createEventDispatcher();
function save() {
dispatch('updateCatch', { pokedexEntry, catchRecord });
}
</script>
<div
class="container bg-red-500 text-white rounded-lg shadow-md p-6 flex flex-col md:flex-row gap-4"
>
<div class="dex-column pokedex-entry-container">
<div class="flex mb-2">
<div class="sprite-container flex justify-center items-center bg-white rounded-lg p-2">
<!-- <PokemonSprite
pokedexNumber={pokedexEntry.pokedexNumber.toString().padStart(3, '0')}
form={pokedexEntry.form
.replace(/[^a-zA-Z ]/g, '')
.trim()
.replace(/ /g, '-')}
/> -->
</div>
<div class="pl-2">
<h3 class="text-xl font-bold pt-1">{pokedexEntry.pokemon}</h3>
<sub class="text-gray-200">#{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</sub>
</div>
</div>
<div class="bg-white text-black rounded-lg p-4 mb-2">
<p><strong>Form:</strong> {pokedexEntry.form ? pokedexEntry.form : '-'}</p>
</div>
<div class="bg-white text-black rounded-lg p-4">
<p><strong>Box:</strong> {pokedexEntry.boxPlacement.box}</p>
<p><strong>Row:</strong> {pokedexEntry.boxPlacement.row}</p>
<p><strong>Column:</strong> {pokedexEntry.boxPlacement.column}</p>
<p><strong>Can Gigantamax:</strong> {pokedexEntry.canGigantamax ? 'Yes' : 'No'}</p>
<p><strong>Notes:</strong> {pokedexEntry.notes}</p>
</div>
</div>
<div class="dex-column catch-record-container bg-white text-black rounded-lg p-4 mb-4 md:mb-0">
<div class="flex items-center">
<label class="block font-bold mr-2" for={`caughtInput-${catchRecord._id}`}>Caught:</label>
<input
type="checkbox"
id={`caughtInput-${catchRecord._id}`}
bind:checked={catchRecord.caught}
class="form-checkbox"
/>
</div>
<div class="flex items-center">
<label class="block font-bold mr-2" for={`haveToEvolveInput-${catchRecord._id}`}
>Needs to evolve:</label
>
<input
type="checkbox"
id={`haveToEvolveInput-${catchRecord._id}`}
bind:checked={catchRecord.haveToEvolve}
class="form-checkbox"
/>
</div>
<div class="flex items-center">
<label class="block font-bold mr-2" for={`inHomeInput-${catchRecord._id}`}>In home:</label>
<input
type="checkbox"
id={`inHomeInput-${catchRecord._id}`}
bind:checked={catchRecord.inHome}
class="form-checkbox"
/>
</div>
{#if pokedexEntry.canGigantamax}
<div class="flex items-center">
<label class="block font-bold mr-2" for={`hasGigantamaxedInput-${catchRecord._id}`}
>Has Gigantamaxed:</label
>
<input
type="checkbox"
id={`hasGigantamaxedInput-${catchRecord._id}`}
bind:checked={catchRecord.hasGigantamaxed}
class="form-checkbox"
/>
</div>
{/if}
<p>
<label class="block font-bold mb-1" for={`personalNotesInput-${catchRecord._id}`}
>Notes:</label
>
<textarea
bind:value={catchRecord.personalNotes}
id={`personalNotesInput-${catchRecord._id}`}
class="form-textarea w-full p-2 border rounded"
></textarea>
</p>
</div>
<div class="dex-column additional-details-container">
<div class="bg-white text-black rounded-lg p-4 mb-2">
<p><strong>Region to Catch In:</strong> {pokedexEntry.regionToCatchIn}</p>
<p><strong>Games to catch in:</strong></p>
<ul class="list-disc list-inside">
{#each pokedexEntry.gamesToCatchIn as game}
<li>{game}</li>
{/each}
</ul>
{#if pokedexEntry.regionToEvolveIn}
<p><strong>Region to Evolve In:</strong> {pokedexEntry.regionToEvolveIn}</p>
{/if}
</div>
<div class="bg-white text-black rounded-lg p-4">
<button on:click={save}>Save</button>
</div>
</div>
</div>
<style>
.container {
max-width: 1000px;
margin: 10px;
}
.dex-column {
width: 300px;
}
.pokedex-entry-container h3 {
color: #ffd700; /* Gold color */
}
.sprite-container {
width: 68px;
height: 68px;
}
.form-checkbox {
appearance: none;
background-color: #fff;
border: 2px solid #000;
border-radius: 0.25rem;
width: 1.5rem;
height: 1.5rem;
display: inline-block;
position: relative;
}
.form-checkbox:checked {
background-color: #00bfff;
background-size: 100% 100%;
background-position: center center;
background-repeat: no-repeat;
}
.form-textarea {
min-height: 3rem;
background-color: #fff;
}
</style>
+24
View File
@@ -0,0 +1,24 @@
import mongoose, { Schema, Document, Types } from 'mongoose';
export interface CatchRecord extends Document {
userId: string;
pokedexEntryId: Types.ObjectId;
haveToEvolve: boolean;
caught: boolean;
inHome: boolean;
hasGigantamaxed: boolean;
personalNotes: string;
}
const catchRecordSchema = new Schema<CatchRecord>({
userId: String,
pokedexEntryId: { type: Schema.Types.ObjectId, ref: 'PokedexEntry', required: true },
haveToEvolve: { type: Boolean, default: false },
caught: { type: Boolean, default: false },
inHome: { type: Boolean, default: false },
hasGigantamaxed: { type: Boolean, default: false },
personalNotes: String
});
const CatchRecordModel = mongoose.model<CatchRecord>('CatchRecord', catchRecordSchema);
export default CatchRecordModel;
+7
View File
@@ -0,0 +1,7 @@
import { type PokedexEntry } from './PokedexEntry';
import { type CatchRecord } from './CatchRecord';
export interface CombinedData {
pokedexEntry: PokedexEntry;
catchRecord: CatchRecord;
}
@@ -0,0 +1,35 @@
import CatchRecordModel, { type CatchRecord } from '$lib/models/CatchRecord';
class CatchRecordRepository {
async findById(id: string): Promise<CatchRecord | null> {
return CatchRecordModel.findById(id).exec();
}
async findAll(): Promise<CatchRecord[]> {
return CatchRecordModel.find().exec();
}
async create(data: Partial<CatchRecord>): Promise<CatchRecord> {
return CatchRecordModel.create(data);
}
async update(id: string, data: Partial<CatchRecord>): Promise<CatchRecord | null> {
return CatchRecordModel.findByIdAndUpdate(id, data, { new: true }).exec();
}
async delete(id: string): Promise<void> {
await CatchRecordModel.findByIdAndDelete(id).exec();
}
async upsert(data: Partial<CatchRecord>): Promise<CatchRecord | null> {
if (data._id) {
// Update existing record
return CatchRecordModel.findByIdAndUpdate(data._id, data, { new: true }).exec();
} else {
// Create new record
return CatchRecordModel.create(data);
}
}
}
export default CatchRecordRepository;