| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- <template>
- <main class="models--page">
- <div class="models--container">
- <!-- 필터 -->
- <div class="models--filter--section">
- <div class="filter--group">
- <!-- 연료 타입 필터 -->
- <div class="filter--dropdown--list">
- <h2>연료 타입</h2>
- <div class="filter--dropdown">
- <button
- v-for="fuel in filters.fuelType"
- :key="fuel.id"
- :class="['filter--btn', { active: activeFuelTypes.includes(fuel.id) }]"
- @click="toggleFuelType(fuel.id)"
- >
- <svg
- v-if="fuel.id == 'etron'"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use
- v-if="activeFuelTypes.includes(fuel.id)"
- href="/img/select-xs.svg#main"
- ></use>
- <use v-else href="/img/charging-xs.svg#main"></use>
- </svg>
- <svg
- v-else-if="activeFuelTypes.includes(fuel.id)"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use href="/img/select-xs.svg#main"></use>
- </svg>
- {{ fuel.name }}
- </button>
- </div>
- </div>
- <!-- 그룹 네임 필터 -->
- <div class="filter--dropdown--list">
- <h2>모델</h2>
- <div class="filter--dropdown">
- <button
- v-for="group in filters.groupName"
- :key="group.id"
- :class="['filter--btn', { active: activeGroupNames.includes(group.id) }]"
- @click="toggleGroupName(group.id)"
- >
- <svg
- v-if="activeGroupNames.includes(group.id)"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use href="/img/select-xs.svg#main"></use>
- </svg>
- {{ group.name }}
- </button>
- </div>
- </div>
- <!-- 바디 타입 필터 -->
- <div class="filter--dropdown--list">
- <h2>모델 유형</h2>
- <div class="filter--dropdown">
- <button
- v-for="body in filters.bodyType"
- :key="body.id"
- :class="['filter--btn', { active: activeBodyTypes.includes(body.id) }]"
- @click="toggleBodyType(body.id)"
- >
- <svg
- v-if="activeBodyTypes.includes(body.id)"
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use href="/img/select-xs.svg#main"></use>
- </svg>
- {{ body.name }}
- </button>
- </div>
- </div>
- </div>
- </div>
- <!-- 차량 그리드 (필터 선택되지 않았을 때만 표시) -->
- <div class="models--list--wrap">
- <div v-if="!isFilterActive" class="all--models">
- 전체 모델({{ filteredModels.length }})
- </div>
- <div v-if="!isFilterActive" class="models--list">
- <div
- v-for="model in filteredModels"
- :key="model.id"
- class="model--item"
- @click="handleModelClick(model)"
- >
- <!-- 이미지 -->
- <h2 class="model--name">
- {{ model.groupName }}
- <div class="etron--wrap" v-if="model.fuelType === 'etron'">
- <div class="etron">
- <svg
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use href="/img/charging-xs.svg#main"></use>
- </svg>
- </div>
- </div>
- </h2>
- <div class="model--image--wrap">
- <img :src="model.image" :alt="model.name" />
- </div>
- <!-- 정보 -->
- <div class="model--info--wrap">
- {{ getGroupModelCount(model.groupName) }}개의 모델
- <i class="ico"></i>
- </div>
- </div>
- </div>
- <!-- 모든 차량 리스트 (필터 선택 시 표시) -->
- <div v-if="isFilterActive" class="models--list--car">
- <div class="all--car--title">모든 차량 ({{ filteredCars.length }})</div>
- <div class="car--list">
- <div v-for="car in filteredCars" :key="car.id" class="car--item">
- <div class="bedge--wrap">
- <div class="etron--wrap" v-if="car.fuelType === 'etron'">
- <div class="etron">
- <svg
- fill="none"
- xmlns="http://www.w3.org/2000/svg"
- aria-hidden="true"
- width="16px"
- height="16px"
- class="sc-AxhUy kMyssS sc-fzoant LAaNs"
- >
- <use href="/img/charging-xs.svg#main"></use>
- </svg>
- Electrified
- </div>
- </div>
- </div>
- <div class="car--image">
- <NuxtLink :to="car.link">
- <img :src="car.image" :alt="car.name" />
- </NuxtLink>
- </div>
- <div class="car--info">
- <h3 class="car--name">{{ car.fullName }}</h3>
- <NuxtLink :to="car.link" class="car--link">자세히 보기</NuxtLink>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </main>
- </template>
- <script setup>
- const modelsData = ref({
- models: [],
- filters: { fuelType: [], bodyType: [], groupName: [] },
- });
- const activeFuelTypes = ref([]);
- const activeBodyTypes = ref([]);
- const activeGroupNames = ref([]);
- // 필터 옵션
- const filters = computed(() => modelsData.value.filters);
- // 필터 토글 함수
- const toggleFuelType = (value) => {
- const index = activeFuelTypes.value.indexOf(value);
- if (index > -1) {
- activeFuelTypes.value.splice(index, 1);
- } else {
- activeFuelTypes.value.push(value);
- }
- };
- const toggleBodyType = (value) => {
- const index = activeBodyTypes.value.indexOf(value);
- if (index > -1) {
- activeBodyTypes.value.splice(index, 1);
- } else {
- activeBodyTypes.value.push(value);
- }
- };
- const toggleGroupName = (value) => {
- const index = activeGroupNames.value.indexOf(value);
- if (index > -1) {
- activeGroupNames.value.splice(index, 1);
- } else {
- activeGroupNames.value.push(value);
- }
- };
- // groupName별 모델 개수를 계산하는 함수
- const getGroupModelCount = (groupName) => {
- return modelsData.value.models.filter((model) => model.groupName === groupName)
- .length;
- };
- // 연료 타입 이름 가져오기
- const getFuelTypeName = (fuelType) => {
- const fuelTypes = {
- etron: "전기차",
- hybrid: "하이브리드",
- "gas-diesel": "가솔린/디젤",
- };
- return fuelTypes[fuelType] || fuelType;
- };
- // 필터가 활성화되어 있는지 확인
- const isFilterActive = computed(() => {
- return (
- activeFuelTypes.value.length > 0 ||
- activeBodyTypes.value.length > 0 ||
- activeGroupNames.value.length > 0
- );
- });
- // 모델 그룹 클릭 핸들러
- const handleModelClick = (model) => {
- // 해당 그룹을 필터에 추가
- if (!activeGroupNames.value.includes(model.groupName)) {
- activeGroupNames.value.push(model.groupName);
- }
- // 해당 연료 타입을 필터에 추가
- if (model.fuelType && !activeFuelTypes.value.includes(model.fuelType)) {
- activeFuelTypes.value.push(model.fuelType);
- }
- };
- // 필터링된 차량 리스트 (모든 차량)
- const filteredCars = computed(() => {
- // 필터가 활성화되지 않은 경우
- if (!isFilterActive.value) {
- return [];
- }
- let filtered = modelsData.value.models;
- // 연료 타입 필터
- if (activeFuelTypes.value.length > 0) {
- filtered = filtered.filter((model) =>
- activeFuelTypes.value.includes(model.fuelType)
- );
- }
- // 바디 타입 필터
- if (activeBodyTypes.value.length > 0) {
- filtered = filtered.filter((model) =>
- model.bodyType.some((type) => activeBodyTypes.value.includes(type))
- );
- }
- // 그룹 네임 필터
- if (activeGroupNames.value.length > 0) {
- filtered = filtered.filter((model) =>
- activeGroupNames.value.includes(model.groupName)
- );
- }
- return filtered;
- });
- // 필터링된 모델 계산 (그룹화된 모델)
- const filteredModels = computed(() => {
- let filtered = modelsData.value.models;
- // 연료 타입 필터 (OR 조건 - 선택된 연료 타입 중 하나라도 일치하면 포함)
- if (activeFuelTypes.value.length > 0) {
- filtered = filtered.filter((model) =>
- activeFuelTypes.value.includes(model.fuelType)
- );
- }
- // 바디 타입 필터 (OR 조건 - 선택된 바디 타입 중 하나라도 일치하면 포함)
- if (activeBodyTypes.value.length > 0) {
- filtered = filtered.filter((model) =>
- model.bodyType.some((type) => activeBodyTypes.value.includes(type))
- );
- }
- // 그룹 네임 필터 (OR 조건 - 선택된 그룹 네임 중 하나라도 일치하면 포함)
- if (activeGroupNames.value.length > 0) {
- filtered = filtered.filter((model) =>
- activeGroupNames.value.includes(model.groupName)
- );
- }
- // groupName별로 그룹화하고 각 그룹의 첫 번째 모델만 추출
- const groupedByName = {};
- filtered.forEach((model) => {
- // groupName을 키로 사용
- const groupName = model.groupName;
- // 해당 groupName 그룹이 없으면 생성하고 첫 번째 모델 저장
- if (!groupedByName[groupName]) {
- groupedByName[groupName] = model;
- }
- });
- // 그룹화된 객체에서 값(첫 번째 모델들)만 배열로 반환
- return Object.values(groupedByName);
- });
- onMounted(async () => {
- try {
- const response = await fetch("/models.json");
- const data = await response.json();
- modelsData.value = data;
- console.log("Models data loaded:", data);
- } catch (error) {
- console.error("Failed to load models data:", error);
- }
- });
- </script>
|