aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2024-03-12 19:18:52 +0000
committerLeonardo Bishop <me@leonardobishop.com>2024-03-12 19:18:52 +0000
commita4052ffee8bc7c6c8a69eba5120b5c6c2d951b0f (patch)
tree970921e587c0972ed4bf8a82a18bbad8dee10458 /components
parentaddf95bc7e1e694cd9ba7797c8b0847bfecaf54c (diff)
Add items
Diffstat (limited to 'components')
-rw-r--r--components/base/ItemStack/ItemStackModal.vue19
-rw-r--r--components/base/ItemStack/ItemStackPicker.vue3
-rw-r--r--components/editor/EditorSidebar.vue16
-rw-r--r--components/editor/EditorSidebarItem.vue66
-rw-r--r--components/editor/task/EditorTaskConfigurationRow.vue2
-rw-r--r--components/header/PageHeader.vue56
6 files changed, 157 insertions, 5 deletions
diff --git a/components/base/ItemStack/ItemStackModal.vue b/components/base/ItemStack/ItemStackModal.vue
index 7cf4db9..865c054 100644
--- a/components/base/ItemStack/ItemStackModal.vue
+++ b/components/base/ItemStack/ItemStackModal.vue
@@ -3,12 +3,11 @@ import { computed, ref } from 'vue';
import materials from '@/lib/materials';
const model = defineModel();
-
const emit = defineEmits(['confirm']);
-
const props = defineProps<{
value: any
}>();
+const session = useSessionStore();
//TODO unshitify
const value = ref<any>(props.value);
@@ -42,6 +41,17 @@ const selectedType = ref(
const noTypeSelected = computed(() => selectedType.value === '');
const noValue = computed(() => !isQuestItem.value && !isItemStack.value && !isMaterial.value);
+const selectedQuestItem = computed({
+ get() {
+ return value.value?.['quest-item'];
+ },
+ set(newValue: string) {
+ value.value = {}
+ value.value['quest-item'] = newValue;
+ }
+})
+const knownQuestItems = computed(() => { return session.session.items.map((item) => item.id) });
+
const setSelectedType = (type: string) => {
if (type === 'questitem') {
value.value = {};
@@ -98,6 +108,11 @@ const confirm = () => {
<ItemStackForm v-model="value" />
</div>
+ <div id="quest-item" class="option-group" v-if="selectedType === 'questitem'">
+ <label for="quest-item">Quest Item</label>
+ <multiselect v-model="selectedQuestItem" :options="knownQuestItems" :searchable="true"
+ placeholder="Enter quest item" />
+ </div>
<div id="confirm" class="control-group">
<Button :icon="['fas', 'times']" :label="'Cancel'" @click="model = false"></Button>
diff --git a/components/base/ItemStack/ItemStackPicker.vue b/components/base/ItemStack/ItemStackPicker.vue
index bb0b84d..2dc35d3 100644
--- a/components/base/ItemStack/ItemStackPicker.vue
+++ b/components/base/ItemStack/ItemStackPicker.vue
@@ -49,7 +49,8 @@ const update = (newValue: any) => {
<template>
<div class="itemstack" @click="showItemStackModal = true">
<span v-if="empty" class="empty">ItemStack...</span>
- <span v-if="isQuestItem" class="item"><font-awesome-icon :icon="['fas', 'tag']" /> Quest Item</span>
+ <span v-if="isQuestItem" class="item"><font-awesome-icon :icon="['fas', 'tag']" /> Quest Item: {{
+ value['quest-item'] }}</span>
<span v-if="isItemStack" class="item"><font-awesome-icon :icon="['fas', 'cube']" /> ItemStack: {{ value.type ||
value.item || value.material }}</span>
<span v-if="isMaterial" class="item"><font-awesome-icon :icon="['fas', 'apple-whole']" /> {{ value }}</span>
diff --git a/components/editor/EditorSidebar.vue b/components/editor/EditorSidebar.vue
index 992dd86..48e187f 100644
--- a/components/editor/EditorSidebar.vue
+++ b/components/editor/EditorSidebar.vue
@@ -24,7 +24,7 @@ const setSelectedType = (type: 'quests' | 'items') => {
</span>
<span class="option" @click="setSelectedType('items')" :class="{ selected: currentType === 'items' }">
<span>
- <font-awesome-icon :icon="['fas', 'cube']" />
+ <font-awesome-icon :icon="['fas', 'cubes']" />
Items
</span>
</span>
@@ -34,6 +34,13 @@ const setSelectedType = (type: 'quests' | 'items') => {
<EditorSidebarQuest
v-for="quest in session.quests.filter((q) => (!session.categories.some((c) => c.id === q.options.category)))"
:key="quest.id" :quest="quest" />
+ <p id="count">{{ session.quests.length }} quest{{ session.quests.length === 1 ? '' : 's' }}, {{
+ session.categories.length }}
+ categor{{ session.categories.length === 1 ? 'y' : 'ies' }}</p>
+ </div>
+ <div id="items" v-if="currentType === 'items'">
+ <EditorSidebarItem v-for="item in session.items" :key="item.id" :item="item" />
+ <p id="count">{{ session.items.length }} item{{ session.items.length === 1 ? '' : 's' }}</p>
</div>
<div id="configuration-container">
<EditorSidebarMainConfiguration />
@@ -99,5 +106,12 @@ const setSelectedType = (type: 'quests' | 'items') => {
bottom: 0;
width: 100%
}
+
+ #count {
+ margin: 0.5rem 0;
+ font-size: 0.7rem;
+ text-align: center;
+ color: var(--color-text-mute);
+ }
}
</style> \ No newline at end of file
diff --git a/components/editor/EditorSidebarItem.vue b/components/editor/EditorSidebarItem.vue
new file mode 100644
index 0000000..4696bb1
--- /dev/null
+++ b/components/editor/EditorSidebarItem.vue
@@ -0,0 +1,66 @@
+<script setup lang="ts">
+import { computed, toRefs } from 'vue';
+
+const props = defineProps<{
+ item: EditorItem;
+}>();
+
+const { item } = toRefs(props);
+
+const route = useRoute();
+
+const setSelectedItem = () => {
+ navigateTo({ path: `/item/${item.value.id}` })
+};
+
+const selected = computed(() => {
+ return route.path.startsWith('/item') && route.params.id === item.value.id;
+});
+</script>
+
+<template>
+ <div id="item-container" @click.stop="setSelectedItem" :class="{ selected: selected }">
+ <span id="item-title">
+ <font-awesome-icon class="item-icon" :icon="['fas', 'cube']" />
+ <span id="item-name">
+ <span id="item-display-id">{{ item.id }}</span>
+ <code id="item-display-type">{{ item.type }}</code>
+ </span>
+ </span>
+ </div>
+</template>
+
+<style scoped>
+#item-container {
+ cursor: pointer;
+ padding: 0.3rem 1rem;
+ transition: background-color 0.3s;
+
+ #item-title {
+ display: flex;
+ align-items: center;
+ margin: 0;
+ gap: 0.6rem;
+ font-size: 0.8rem;
+
+ #item-name {
+ display: flex;
+ flex-direction: column;
+ align-items: left;
+
+ #item-display-type {
+ font-size: 0.6rem;
+ color: var(--color-text-mute);
+ }
+ }
+ }
+}
+
+.selected {
+ background-color: var(--color-primary-mute) !important;
+}
+
+#item-container:hover {
+ background-color: var(--color-hover);
+}
+</style> \ No newline at end of file
diff --git a/components/editor/task/EditorTaskConfigurationRow.vue b/components/editor/task/EditorTaskConfigurationRow.vue
index 666669d..c00896f 100644
--- a/components/editor/task/EditorTaskConfigurationRow.vue
+++ b/components/editor/task/EditorTaskConfigurationRow.vue
@@ -41,7 +41,7 @@ if (props.initialValue !== currentValue.value) {
emit('update', currentValue.value);
}
-const error = computed(() => currentValue.value === undefined || currentValue.value === null || currentValue.value === '' || (Array.isArray(currentValue.value) && currentValue.value.length === 0));
+const error = computed(() => currentValue.value === undefined || currentValue.value === null || currentValue.value === '' || (Array.isArray(currentValue.value) && currentValue.value.length === 0) || (typeof currentValue.value === 'object' && Object.keys(currentValue.value).length === 0));
const updateValue = (value: any) => {
currentValue.value = value;
};
diff --git a/components/header/PageHeader.vue b/components/header/PageHeader.vue
new file mode 100644
index 0000000..3c616ca
--- /dev/null
+++ b/components/header/PageHeader.vue
@@ -0,0 +1,56 @@
+<template>
+ <div id="header">
+ <slot />
+ </div>
+</template>
+
+<style lang="scss">
+#header {
+ padding: 1rem 1rem 0.5rem 1rem;
+ background-color: var(--color-background);
+ border-bottom: 1px solid var(--color-border);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ width: 100%;
+ height: 55px;
+ display: flex;
+ align-items: left;
+ justify-content: space-between;
+ gap: 1rem;
+ position: relative;
+ z-index: 0;
+
+ #path {
+ font-size: 1.2rem;
+ display: flex;
+ gap: 0.5rem;
+ align-items: center;
+
+ .icon {
+ font-size: 0.8rem;
+ }
+
+ .chevron {
+ font-size: 0.8rem;
+ color: var(--color-text-mute);
+ }
+
+ .title {
+ font-weight: 700;
+ }
+
+ code {
+ font-size: 0.8rem;
+ color: var(--color-text-mute);
+ }
+ }
+}
+
+.none-selected {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 1rem;
+ font-size: 1.2rem;
+ color: var(--color-text-mute);
+}
+</style> \ No newline at end of file