Skip to content

Commit

Permalink
feat: adding in a basic mob data editor
Browse files Browse the repository at this point in the history
  • Loading branch information
CollinHerber committed Nov 24, 2024
1 parent 664d19c commit 5aaef5a
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 103 deletions.
96 changes: 96 additions & 0 deletions src/lib/components/EditMobDataModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script lang="ts">
import type { IMobData } from "$lib/models/mob-data";
import { createEventDispatcher } from 'svelte';
import { Accordion, AccordionItem } from 'flowbite-svelte';
export let selectedMob: IMobData | null = null;
const dispatch = createEventDispatcher();
function closeModal() {
dispatch('close');
}
function saveChanges() {
dispatch('save', { updatedMob: selectedMob });
closeModal();
}
function addEntry() {
if (selectedMob) {
selectedMob.entries = [
...selectedMob.entries,
{
prefix: '',
weight: 0,
stats: { level: 0, experience: 0 },
requirements: '',
affixes: []
}
];
}
}
function deleteEntry(index: number) {
if (selectedMob) {
selectedMob.entries = selectedMob.entries.filter((_, i) => i !== index);
}
}
function updateEntry(index: number, field: string, value: any) {
if (selectedMob) {
selectedMob.entries[index][field] = value;
selectedMob.entries = [...selectedMob.entries];
}
}
</script>

<div class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div class="bg-white p-4 rounded-lg shadow-lg w-1/2">
<h2 class="text-xl font-bold mb-4">Edit Mob Data</h2>
<p>Editing data for: {selectedMob?.friendlyName}</p>

{#if selectedMob}
<div class="mb-4">
<button class="text-blue-500 hover:underline" on:click={addEntry}>Add Entry</button>
</div>

<Accordion>
{#each selectedMob.entries as entry, index}
<AccordionItem>
<span slot="header">
{selectedMob?.friendlyName} Entry {index + 1} - {entry.prefix}
</span>
<div class="mb-4 border p-2 rounded">
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700">Prefix</label>
<input type="text" class="block w-full mt-1" bind:value={entry.prefix} on:input={(e) => updateEntry(index, 'prefix', e.target?.value)} />
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700">Weight</label>
<input type="number" class="block w-full mt-1" bind:value={entry.weight} on:input={(e) => updateEntry(index, 'weight', e.target?.value)} />
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700">Level</label>
<input type="number" class="block w-full mt-1" bind:value={entry.stats.level} on:input={(e) => updateEntry(index, 'stats.level', e.target?.value)} />
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700">Experience</label>
<input type="number" class="block w-full mt-1" bind:value={entry.stats.experience} on:input={(e) => updateEntry(index, 'stats.experience', e.target?.value)} />
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700">Requirements</label>
<input type="text" class="block w-full mt-1" bind:value={entry.requirements} on:input={(e) => updateEntry(index, 'requirements', e.target?.value)} />
</div>
<button class="text-red-500 hover:underline" on:click={() => deleteEntry(index)}>Delete Entry</button>
</div>
</AccordionItem>
{/each}
</Accordion>
{/if}

<div class="mt-4 flex justify-end space-x-4">
<button class="text-blue-500 hover:underline" on:click={closeModal}>Cancel</button>
<button class="text-blue-500 hover:underline" on:click={saveChanges}>Save</button>
</div>
</div>
</div>
240 changes: 137 additions & 103 deletions src/routes/mod-data/mobs/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,114 +1,148 @@
<script lang="ts">
import { onMount } from 'svelte';
import { ModDataService } from '$lib/services/mod-data-service';
let modDataService = new ModDataService();
import type { IMobData } from '$lib/models/mob-data';
import { onMount } from 'svelte';
import { ModDataService } from '$lib/services/mod-data-service';
import EditModal from '$lib/components/EditMobDataModal.svelte';
let modDataService = new ModDataService();
import type { IMobData } from '$lib/models/mob-data';
let mobData: IMobData[] = [];
let filteredMobData: IMobData[] = [];
let searchQuery: string = '';
let error: string | null = null;
let mobData: IMobData[] = [];
let filteredMobData: IMobData[] = [];
let searchQuery: string = '';
let error: string | null = null;
let isEditModalOpen = false;
let selectedMob: IMobData | null = null;
onMount(() => {
// Load mob data
modDataService.getMobData().then((data) => {
mobData = data;
filteredMobData = [...mobData]; // Initialize filtered data with all mob data
});
});
onMount(() => {
// Load mob data
modDataService.getMobData().then((data) => {
mobData = data;
filteredMobData = [...mobData]; // Initialize filtered data with all mob data
});
});
function handleSearch(event: Event) {
const query = (event.target as HTMLInputElement).value.toLowerCase();
searchQuery = query;
function handleSearch(event: Event) {
const query = (event.target as HTMLInputElement).value.toLowerCase();
searchQuery = query;
if (!query) {
filteredMobData = [...mobData];
} else {
filteredMobData = mobData.filter((mob) =>
mob.friendlyName.toLowerCase().includes(query)
);
}
}
if (!query) {
filteredMobData = [...mobData];
} else {
filteredMobData = mobData.filter((mob) =>
mob.friendlyName.toLowerCase().includes(query)
);
}
}
function openEditModal(mob: IMobData) {
selectedMob = mob;
isEditModalOpen = true;
}
function closeEditModal() {
isEditModalOpen = false;
selectedMob = null;
}
function saveMobData(event: CustomEvent) {
const { updatedMob } = event.detail;
mobData = mobData.map(mob => mob.netId === updatedMob.netId ? updatedMob : mob);
filteredMobData = [...mobData];
closeEditModal();
}
</script>

<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">Mob Data</h1>
<h1 class="text-2xl font-bold mb-4">Mob Data</h1>

<!-- Search Input -->
<div class="mb-4">
<label
for="search"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>
Search Mobs
</label>
<input
id="search"
type="text"
bind:value={searchQuery}
on:input={handleSearch}
placeholder="Type to search by name..."
class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 dark:text-gray-400 focus:ring focus:ring-blue-300 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
/>
</div>

<!-- Search Input -->
<div class="mb-4">
<label
for="search"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>
Search Mobs
</label>
<input
id="search"
type="text"
bind:value={searchQuery}
on:input={handleSearch}
placeholder="Type to search by name..."
class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 dark:text-gray-400 focus:ring focus:ring-blue-300 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
/>
</div>
<!-- Error Message -->
{#if error}
<div class="text-red-500 mb-4">{error}</div>
{/if}

<!-- Error Message -->
{#if error}
<div class="text-red-500 mb-4">{error}</div>
{/if}
<!-- Mob Data Table -->
{#if filteredMobData.length > 0}
<div class="overflow-x-auto relative shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">Net ID</th>
<th scope="col" class="px-6 py-3">Name</th>
<th scope="col" class="px-6 py-3">Entries</th>
<th scope="col" class="px-6 py-3">Actions</th>
</tr>
</thead>
<tbody>
{#each filteredMobData as mob}
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<td class="px-6 py-4">{mob.netId}</td>
<td class="px-6 py-4">{mob.friendlyName}</td>
<td class="px-6 py-4">
<ul>
{#each mob.entries as entry}
<li class="my-2">
<div>
<strong>Prefix:</strong> {entry.prefix || 'N/A'}
</div>
<div>
<strong>Weight:</strong> {entry.weight}
</div>
<div>
<strong>Stats:</strong> Level {entry.stats.level}, Experience {entry.stats.experience}
</div>
<div>
<strong>Requirements:</strong> {entry.requirements}
</div>
{#if entry.affixes?.length > 0}
<div>
<strong>Affixes:</strong>
<ul>
{#each entry.affixes as affix}
<li>{affix.name}</li>
{/each}
</ul>
</div>
{/if}
</li>
{/each}
</ul>
</td>
<td class="px-6 py-4">
<button
class="text-blue-500 hover:underline"
on:click={() => openEditModal(mob)}
>
Edit
</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<p class="text-gray-500 text-sm">No mobs found matching the search criteria.</p>
{/if}
</div>

<!-- Mob Data Table -->
{#if filteredMobData.length > 0}
<div class="overflow-x-auto relative shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">Net ID</th>
<th scope="col" class="px-6 py-3">Name</th>
<th scope="col" class="px-6 py-3">Entries</th>
</tr>
</thead>
<tbody>
{#each filteredMobData as mob}
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<td class="px-6 py-4">{mob.netId}</td>
<td class="px-6 py-4">{mob.friendlyName}</td>
<td class="px-6 py-4">
<ul>
{#each mob.entries as entry}
<li class="my-2">
<div>
<strong>Prefix:</strong> {entry.prefix || 'N/A'}
</div>
<div>
<strong>Weight:</strong> {entry.weight}
</div>
<div>
<strong>Stats:</strong> Level {entry.stats.level}, Experience {entry.stats.experience}
</div>
<div>
<strong>Requirements:</strong> {entry.requirements}
</div>
{#if entry.affixes?.length > 0}
<div>
<strong>Affixes:</strong>
<ul>
{#each entry.affixes as affix}
<li>{affix.name}</li>
{/each}
</ul>
</div>
{/if}
</li>
{/each}
</ul>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<p class="text-gray-500 text-sm">No mobs found matching the search criteria.</p>
{/if}
</div>
<!-- Edit Modal -->
{#if isEditModalOpen}
<EditModal {selectedMob} on:close={closeEditModal} on:save={saveMobData} />
{/if}

0 comments on commit 5aaef5a

Please sign in to comment.