-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding in a basic mob data editor
- Loading branch information
1 parent
664d19c
commit 5aaef5a
Showing
2 changed files
with
233 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |