21.03.15 lamplight서비스 프로젝트(리스트 검색기능 구현 진행중..)

2021. 3. 15. 22:09Vue.js/Spring & Vue APP 프로젝트(프론트엔드)

# NOTE

https://learnvue.co/2020/12/setting-up-your-first-vue3-project-vue-3-0-release/

https://codepen.io/rbqja5597/pen/XWjqOGN?editors=1000

# 주요 소스코드

<DirectorList.vue>

<template>
  <!-- 메인-지도사 리스트 시작 -->
  <section class="directorList-section bg-gray-500">
    <div class="h-2 bg-gray-500"></div>
    <!--리스트 search 시작-->
    <form class="flex h-10 directorList-section-search m-2 text-right rounded-md">
      <select ref="searchKeywordTypeElRef" class="h-full w-full" id="">
        <option value="name">이름</option>
        <option value="nickname">닉네임</option>
        <option value="loginId">아이디</option>
      </select>
      <select ref="pageElRef" id="">
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
      <input ref="searchKeywordElRef" class="h-full w-full rounded-l-md pl-4" type="text" placeholder="검색어 입력" v-model="searchKeyword">
      <button class="w-20 text-white rounded-r-md bg-blue-500" type="button">검색</button>
    </form>
    {{ searchKeyword }}
    <!--리스트 search 끝-->
    <!--리스트 grid 시작-->
    <div class="directorList-section-grid grid grid-cols-1 md:grid-cols-3 gap-3 overflow-hidden">
      <!--리스트 grid__body 시작-->
      <div class="mt-6" v-bind:key="member.id" v-for="member in filteredMembers">
      <div class="directorList-section-grid__body p-8 bg-white m-2 border rounded-xl">
        <!--프로필 이미지-->
        <div class="flex justify-center overflow-hidden">
          <img class="h-96 rounded-lg object-cover object-center" src="https://taegon.kim/wp-content/uploads/2018/05/image-5.png">
        </div>
        <!--이름-->
        <div class="text-center m-4">
          <router-link to="/director/profile" class="text-indigo-500 font-bold text-xl md:text-2xl hover:text-gray-700">
            {{ member.name }}
          </router-link>
        </div>
        <!--소개멘트-->
        <h1 class="font-semibold text-gray-900 leading-none text-xl mt-1 mb-3 capitalize break-normal">
          소개멘트 작성란입니다.
        </h1>
        <!--활동이력-->
        <div class="max-w-full border mt-2 p-1 pl-2 rounded-md">
          <p class="text-base font-medium tracking-wide text-gray-600 mt-1">
            {{ member.cellphoneNo }}
          </p>
          <p class="text-base font-medium tracking-wide text-gray-600 mt-1">
            {{ member.email }}
          </p>
          <p class="text-base font-medium tracking-wide text-gray-600 mt-1">
            {{ member.regDate }}
          </p>
        </div>
        <button class="btn-primary mt-2 h-10 w-full rounded-md">
          선택
        </button>
        <!--평점-->
        <div class="flex justify-center items-center w-full text-center mt-3">
          <div class="font-bold text-xl mr-5">
            '{{ member.name }}'님의 전체 평점
          </div>
          <div class="border rounded-full h-24 w-24 bg-yellow-500 flex justify-center items-center">
            <div class="font-bold text-2xl text-white">
              4.5/5
            </div>
          </div>
        </div>
        <!--후기-->
        <div class="flex justify-between items-end h-8 w-full border-b-4 font-semibold">
          <p class="pb-1">
            매칭 후기
          </p>
          <div class="text-sm cursor-pointer hover:text-blue-500">
            더보기
          </div>
        </div>
        <div class="mt-2 border-b-2 border-t-2">
            <p class="text-gray-900 p-2">
              후기를 작성합니다. Lorem ipsum dolor sit amet consectetur adipisicing elit. 
            </p>
            <p class="text-gray-500 p-2 text-sm">
              2021-03-11 15:15:15
            </p>
        </div>
        <!--후기-->
        <div class="mt-2 border-b-2 border-t-2">
            <p class="text-gray-900 p-2">
              후기를 작성합니다. ipsum, sapiente earum voluptates reiciendis fuga sit! Minima quaerat sit sed iusto consectetur.
            </p>
            <p class="text-gray-500 p-2 text-sm">
              2021-03-11 15:15:15
            </p>
        </div>
        
      </div>
      </div>
      <!--리스트 grid__body 끝-->
    </div>
    <!--리스트 grid 끝-->
  </section>
  <!-- 메인-지도사 리스트 끝 -->

</template>

<script lang="ts">
import { defineComponent, reactive, ref, getCurrentInstance, onMounted, computed, watch } from 'vue'
import { IMember } from '../types/'
import { MainApi } from '../apis/'

export default defineComponent({
  name: 'DirectorList',

  props: {
    globalShare: {
      type: Object,
      required: true
    },
    boardId: {
      type: Number,
      required: true,
      default:1
    },
  },

  setup(props){
    const mainApi:MainApi = getCurrentInstance()?.appContext.config.globalProperties.$mainApi;

    const state:any = reactive({
      members: [] as IMember[],
      searchKeyword:''
    });
    //21.03.15 리스트 검색기능 구현 진행중..
    //문제점
    // - v-model 바로 안나옴
    // - 검색타입, 페이지 값 어떻게 받고, 어떻게 넘길지.....
    const filteredMembers = computed(() => {
      return state.members.filter((member:IMember) => member.name.includes(state.searchKeyword))
    })
    
    

    function loadMembers(boardId:number, searchKeywordType:string, searchKeyword:string, page:number){
      
      mainApi.member_list(boardId, searchKeywordType, searchKeyword, page)
      .then(axiosResponse => {
          state.members = axiosResponse.data.body.members;
      });

    }

    // onMounted 바로 실행하는 것이 아닌 모든 것이 준비되었을때 실행됨
    onMounted(() => {
      loadMembers(props.boardId, "name", "", 1);
    });

    return{
      state,
      filteredMembers,
    }

  }
})
</script>


<style scoped>
/* https://tailwindcomponents.com/component/blogs-posts-card */
.directorList-section-grid__body{
  min-width: 400px;
}

</style>