Skip to content

Commit

Permalink
Refactor inputs (#30)
Browse files Browse the repository at this point in the history
* Refactor Add Item input

* Refactor tag inputs
  • Loading branch information
GeniJaho authored Jan 12, 2024
1 parent 73db6ae commit a63fa96
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 50 deletions.
1 change: 1 addition & 0 deletions app/Http/Controllers/PhotoItemsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

class PhotoItemsController extends Controller
{
// todo validate the item_id exists
public function store(Photo $photo, Request $request): JsonResponse
{
/** @var User $user */
Expand Down
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"vue": "^3.3.4"
},
"dependencies": {
"@headlessui/vue": "^1.7.17",
"filepond": "^4.30.4",
"filepond-plugin-file-validate-size": "^2.2.8",
"filepond-plugin-file-validate-type": "^1.2.8",
Expand Down
109 changes: 109 additions & 0 deletions resources/js/Components/TagBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<script setup>
import { ref, computed } from 'vue'
import {
Combobox,
ComboboxInput,
ComboboxButton,
ComboboxOptions,
ComboboxOption,
TransitionRoot,
} from '@headlessui/vue';
const props = defineProps({
items: Array,
modelValue: Object,
});
defineEmits(['update:modelValue']);
let query = ref('')
let filteredItems = computed(() => {
const items = query.value === ''
? props.items
: props.items.filter((item) =>
item.name
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, ''))
);
return items.slice(0, 100)
})
</script>

<template>
<Combobox
:modelValue="modelValue"
@update:modelValue="value => $emit('update:modelValue', value)"
by="id"
>
<div class="relative">
<div
class="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm"
>
<ComboboxInput
class="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0"
:displayValue="(item) => item.name"
@change="query = $event.target.value"
/>
<ComboboxButton
class="absolute inset-y-0 right-0 flex items-center pr-2"
>
<svg class="h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z" clip-rule="evenodd" />
</svg>
</ComboboxButton>
</div>
<TransitionRoot
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
@after-leave="query = ''"
>
<ComboboxOptions
class="absolute z-10 mt-1 max-h-96 w-full md:w-96 right-0 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm"
>
<div
v-if="filteredItems.length === 0 && query !== ''"
class="relative cursor-default select-none px-4 py-2 text-gray-700"
>
Nothing found.
</div>

<ComboboxOption
v-for="item in filteredItems"
as="template"
:key="item.id"
:value="item"
v-slot="{ selected, active }"
>
<li
class="relative cursor-default select-none py-2 pl-10 pr-4"
:class="{
'bg-indigo-600 text-white': active,
'text-gray-900': !active,
}"
>
<span
class="block truncate"
:class="{ 'font-medium': selected, 'font-normal': !selected }"
>
{{ item.name }}
</span>
<span
v-if="selected"
class="absolute inset-y-0 left-0 flex items-center pl-3"
:class="{ 'text-white': active, 'text-indigo-600': !active }"
>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</TransitionRoot>
</div>
</Combobox>
</template>
55 changes: 19 additions & 36 deletions resources/js/Pages/Photo/PhotoItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import IconPrimaryButton from "@/Components/IconPrimaryButton.vue";
import ToggleInput from "@/Components/ToggleInput.vue";
import IconDangerButton from "@/Components/IconDangerButton.vue";
import TextInput from "@/Components/TextInput.vue";
import TagBox from "@/Components/TagBox.vue";
const props = defineProps({
item: Object,
tags: Object,
});
const selectedMaterialTag = ref(props.tags.material[0].id);
const selectedBrandTag = ref(props.tags.brand[0].id);
const selectedEventTag = ref(props.tags.event[0].id);
const selectedMaterialTag = ref(props.tags.material[0]);
const selectedBrandTag = ref(props.tags.brand[0]);
const selectedEventTag = ref(props.tags.event[0]);
</script>

<template>
Expand All @@ -32,65 +33,47 @@ const selectedEventTag = ref(props.tags.event[0].id);
</div>
<div class="mt-6">
<div class="flex flex-row justify-between space-x-2">
<select
id="add-material-tag"
<TagBox
class="w-full lg:w-48"
:items="tags.material"
v-model="selectedMaterialTag"
name="add-tag"
class="block w-full lg:w-48 rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6">
<option
v-for="material in tags.material"
:value="material.id"
>{{ material.name }}
</option>
</select>
></TagBox>

<PrimaryButton
class="whitespace-nowrap"
@click="$emit('add-tag-to-item', item.pivot, selectedMaterialTag)"
@click="$emit('add-tag-to-item', item.pivot, selectedMaterialTag.id)"
:disabled="!selectedMaterialTag"
>
Add Material
</PrimaryButton>
</div>

<div class="mt-2 flex flex-row justify-between space-x-2">
<select
id="add-brand-tag"
<TagBox
class="w-full lg:w-48"
:items="tags.brand"
v-model="selectedBrandTag"
name="add-tag"
class="block w-full lg:w-48 rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6">
<option
v-for="brand in tags.brand"
:value="brand.id"
>{{ brand.name }}
</option>
</select>
></TagBox>

<PrimaryButton
class="whitespace-nowrap"
@click="$emit('add-tag-to-item', item.pivot, selectedBrandTag)"
@click="$emit('add-tag-to-item', item.pivot, selectedBrandTag.id)"
:disabled="!selectedBrandTag"
>
Add Brand
</PrimaryButton>
</div>

<div class="mt-2 flex flex-row justify-between space-x-2">
<select
id="add-event-tag"
<TagBox
class="w-full lg:w-48"
:items="tags.event"
v-model="selectedEventTag"
name="add-tag"
class="block w-full lg:w-48 rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6">
<option
v-for="event in tags.event"
:value="event.id"
>{{ event.name }}
</option>
</select>
></TagBox>

<PrimaryButton
class="whitespace-nowrap"
@click="$emit('add-tag-to-item', item.pivot, selectedEventTag)"
@click="$emit('add-tag-to-item', item.pivot, selectedEventTag.id)"
:disabled="!selectedEventTag"
>
Add Event
Expand Down
22 changes: 8 additions & 14 deletions resources/js/Pages/Photo/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import PrimaryButton from "@/Components/PrimaryButton.vue";
import debounce from 'lodash.debounce'
import { router } from '@inertiajs/vue3'
import IconDangerButton from "@/Components/IconDangerButton.vue";
import TagBox from "@/Components/TagBox.vue";
const props = defineProps({
photoId: Number,
Expand All @@ -18,7 +19,7 @@ const props = defineProps({
const photo = ref(null);
const photoItems = ref([]);
const selectedItem = ref(props.items[0].id);
const selectedItem = ref(props.items[0]);
onMounted(() => {
getPhoto();
Expand All @@ -41,7 +42,7 @@ const deletePhoto = () => {
const addItem = () => {
axios.post(`/photos/${photo.value.id}/items`, {
item_id: selectedItem.value,
item_id: selectedItem.value.id,
}).then(() => {
getPhoto();
});
Expand Down Expand Up @@ -139,22 +140,15 @@ const updateItemQuantity = debounce((photoItemId, quantity) => {

<div class="w-full md:w-1/2 xl:w-2/3 px-4">
<div class="flex flex-row mt-6 md:mt-0">
<select
id="add-item"
<TagBox
class="w-full sm:w-96"
:items="items"
v-model="selectedItem"
name="add-item"
class="block w-full sm:w-48 rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6">
<option
v-for="item in items"
:value="item.id"
>{{ item.name }}
</option>
</select>

></TagBox>
<PrimaryButton
class="whitespace-nowrap ml-4"
@click="addItem"
:disabled="selectedItem === ''"
:disabled="!selectedItem"
>
Add Object
</PrimaryButton>
Expand Down

0 comments on commit a63fa96

Please sign in to comment.