Initial commit: PC Builder AdonisJS project
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineEmits, defineProps, onMounted, ref, watch } from 'vue'
|
||||
import { Component } from '~/pages/types/UITypes'
|
||||
|
||||
interface ComponentsByType {
|
||||
type: string
|
||||
components: Component[]
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
availableComponents: Component[]
|
||||
selectedComponents: number[]
|
||||
initialSelectedComponents?: Component[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:components'])
|
||||
|
||||
const componentTypeOrder = [
|
||||
'Processor',
|
||||
'Motherboard',
|
||||
'Graphic Card',
|
||||
'Memory',
|
||||
'HDD',
|
||||
'SSD',
|
||||
'Cooler',
|
||||
'Power Supply',
|
||||
'Case',
|
||||
'WiFi-Card',
|
||||
'Fan',
|
||||
'Other',
|
||||
]
|
||||
|
||||
// Fusionner les composants disponibles et initialement s├®lectionn├®s
|
||||
const allComponents = computed(() => {
|
||||
const mergedComponents = [...props.availableComponents]
|
||||
if (props.initialSelectedComponents) {
|
||||
props.initialSelectedComponents.forEach((component) => {
|
||||
if (!mergedComponents.find((c) => c.id === component.id)) {
|
||||
mergedComponents.push(component)
|
||||
}
|
||||
})
|
||||
}
|
||||
return mergedComponents
|
||||
})
|
||||
|
||||
// Trier les composants par type
|
||||
const componentsByType = computed(() => {
|
||||
const groupedComponents: Record<string, Component[]> = {}
|
||||
|
||||
allComponents.value.forEach((component) => {
|
||||
const type = component.type.name
|
||||
if (!groupedComponents[type]) {
|
||||
groupedComponents[type] = []
|
||||
}
|
||||
groupedComponents[type].push(component)
|
||||
})
|
||||
|
||||
const sortedComponentsByType: ComponentsByType[] = componentTypeOrder.map((type) => ({
|
||||
type,
|
||||
components: groupedComponents[type] || [],
|
||||
}))
|
||||
|
||||
return sortedComponentsByType.filter((group) => group.components.length > 0)
|
||||
})
|
||||
|
||||
// Initialisation de selectedComponents
|
||||
let selectedComponents = ref<number[]>(
|
||||
props.initialSelectedComponents?.map((c) => c.id) || props.selectedComponents || []
|
||||
)
|
||||
// Synchroniser les props avec le composant
|
||||
watch(
|
||||
() => props.selectedComponents,
|
||||
(newVal) => {
|
||||
selectedComponents.value = newVal
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.initialSelectedComponents) {
|
||||
emit(
|
||||
'update:components',
|
||||
props.initialSelectedComponents.map((c) => c.id)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
function updateComponents(event: Event, type: string) {
|
||||
const selectedComponentId = Number((event.target as HTMLSelectElement).value)
|
||||
const updatedComponents = [...selectedComponents.value]
|
||||
|
||||
const alreadyInListComponentIndex = updatedComponents.findIndex((id) => {
|
||||
return selectedComponentId === id
|
||||
})
|
||||
|
||||
if (alreadyInListComponentIndex !== -1) {
|
||||
updatedComponents.splice(alreadyInListComponentIndex, 1)
|
||||
} else {
|
||||
const typeIndex = componentsByType.value.findIndex((item) => item.type === type)
|
||||
const existingComponentIndex = updatedComponents.findIndex((id) => {
|
||||
const component = componentsByType.value[typeIndex].components.find((c) => c.id === id)
|
||||
return component && component.type.unique
|
||||
})
|
||||
if (existingComponentIndex !== -1) updatedComponents.splice(existingComponentIndex, 1)
|
||||
|
||||
if (selectedComponentId != 0) updatedComponents.push(Number(selectedComponentId))
|
||||
}
|
||||
|
||||
selectedComponents.value = updatedComponents
|
||||
emit('update:components', updatedComponents)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="{ type, components } in componentsByType" :key="type">
|
||||
<label :for="`select-${type}`" class="block text-gray-700 text-sm font-bold mb-1 mt-2">
|
||||
{{ type }}
|
||||
</label>
|
||||
<div v-if="components[0]?.type.unique">
|
||||
<!-- Utilisation d'un select pour les composants uniques -->
|
||||
<select
|
||||
@change="updateComponents($event, type)"
|
||||
:id="`select-${type}`"
|
||||
class="w-full mt-2 border-gray-200 focus:border-indigo-600 focus:ring-indigo-500 px-3 py-2 focus:ring-1 border rounded text-gray-700 bg-white"
|
||||
>
|
||||
<option value="" selected>Select a component</option>
|
||||
<option
|
||||
v-for="component in components"
|
||||
:key="component.id"
|
||||
:value="component.id"
|
||||
:selected="selectedComponents.includes(component.id)"
|
||||
>
|
||||
{{ component.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- Utilisation de cases à cocher pour les composants non uniques avec grille responsive -->
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<div v-for="component in components" :key="component.id" class="flex items-center mt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
@click="updateComponents($event, type)"
|
||||
:id="`checkbox-${component.id}`"
|
||||
:value="component.id"
|
||||
v-model="selectedComponents"
|
||||
class="mr-2"
|
||||
:checked="selectedComponents.includes(component.id)"
|
||||
/>
|
||||
<label :for="`checkbox-${component.id}`" class="text-sm text-gray-700">
|
||||
{{ component.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user