= Frontend 구성

== frontend 폴더 구조

sdl-base/frontend 폴더 아래 구성되어 있다.

----
frontend
 |- public <1>
 |- src <2>
 |- static <3>
 |- .env <4>
 |- index.html <5>
 |- package.json <6>
 |- .prettierrc.json <7>
 |- eslint.config.js <8>
 |- vite.config.js <9>
----

<1> build 시 파일명 hashing을 하지 않는 public 폴더
<2> Vue Source 폴더
<3> css, font 등 정적 자원을 포함한 폴더
<4> 배포 대상에 따른 설정 파일(.env에 정의된 파일은 Vue에서 변수로 사용가능)
<5> 프로젝트 index.html
<6> npm 모듈 관리를 위한 파일
<7> prettier 설정 json 파일
<8> eslint 설정 파일
<9> vite 설정 파일

== src

src 폴더는 Vue의 Source 폴더이다. UI 구성을 위한 컴포넌트, 디렉티드, 필더, 라우터, 서비스 등이 있다.

----
src
 |- components <1>
 |- constants <2>
 |- directives <3>
 |- event <4>
 |- filters <5>
 |- i18n <6>
 |- mixin <7>
 |- router <8>
 |- service <9>
 |- utils <10>
 |- vuex <11>
----

<1> 공통 및 화면단 컴포넌트 위치
+
** components/common/control : SDL에서 제공하는 공통 컴포넌트 위치
+
** components/common/popup : SDL에서 제공하는 공통 팝업 위치
+
** components/view : 하위에 업무별로 패키지명을 구분해 폴더 구성
<2> Vue 에서 사용하는 전역 상수 정의
<3> Vue 엘리먼트에서 사용되는 사용자 지정 속성을 정의
<4> Vue3에서 deprecated 된 event bus 모듈 폴더
<5> Vue 에서 텍스트 형식화를 적용할 수 있는 필터 정의
<6> vue-i18n에서 사용하는 다국어관련 정의
<7> Vue mixin 으로 사용하는 변수 및 메소드 정의
<8> Vue를 이용한 단일페이지에서 컴포넌트별 path를 정의
<9> Vue에서 사용하는 service를 정의
<10> SDL에서 제공하는 공통Util 위치
<11> Vue에서 제공하는 상태관리 + 패턴 라이브러리 위치

== components

components 폴더는 SDL에서 제공하는 공통 컴포넌트와 공통 팝업, 어드민 기능 화면을 포함한다.

----
components
 |- common
    |- control <1>
    |- popup <2>
 |- view
    |- admin
        |- approval <3>
        |- approvalTemplate <4>
        |- batch <5>
        |- board <6>
        |- dept <7>
        |- etc <8>
        |- htmlTemplate <9>
        |- log <10>
        |- main <11>
        |- menu <12>
        |- role <13>
        |- sample <14>
        |- user <15>
        |- workgroup <16>
    |- sample <17>
----

<1> SDL 공통컴포넌트
<2> SDL 공통팝업
<3> 결재관리
<4> 결재문서 양식 관리
<5> 배치관리
<6> 게시판관리
<7> 부서관리
<8> 기타관리
<9> HTML 양식 관리
<10> 로그관리
<11> 메인페이지
<12> 메뉴관리
<13> 역할관리
<14> 결재샘플
<15> 사용자관리
<16> 업무그룹관리
<17> 공통컴포넌트 사용 샘플

IMPORTANT: 프로젝트에서 개발한 Vue 화면은 components/view 폴더 아래 있어야 한다. +
router 등록 시 디폴트 경로가 components/view 이다.

== css 위치 및 import 방법
image::front_02_24.png[]
사용하고자 하는 css 를 static/css 밑에 넣어놓고 src/main.js에 import 에서 사용한다.

== directive(사용자 지정속성)
./directives/custom.js
[source, javascript]
----
// v-directive 의 기본 구조
export default {
  beforeMount(el, binding, vnode) {
    // console.log('bind');
  },
  mounted(el, binding, vndoe) {
    // console.log('inserted');
  },
  updated(el, binding, vnode, oldVnode) {
    // console.log('componentUpdated');
  },
};
----
* Vue 엘리먼트에서 사용되는 사용자 지정 속성을 정의한다.
* 디렉티브에서 제공하는 훅 함수는 아래와 같다.
+
** created : 이벤트 리스너가 적용되기 전에 호출된다.
+
** beforeMount : 엘리먼트가 DOM에 삽입되기 직전에 호출된다.
+
** mounted : 바인딩된 엘리먼트의 부모 컴포넌트 및 모든 자식 컴포넌트의 mounted 이후에 호출된다.
+
** beforeUpdate : 부모 컴포넌트의 updated 전에 호출된다.
+
** updated : 바인딩된 엘리먼트의 부모 컴포넌트 및 모든 자식 컴포넌트의 updated 이후에 호출됩니다.
+
** beforeUnmount : 부모 컴포넌트의 beforeUnmount 이후에 호출된다.
+
** unmounted : 부모 컴포넌트의 unmounted 전에 호출된다.
* 참고 : https://v3-docs.vuejs-korea.org/guide/reusability/custom-directives.html#directive-hooks


.directives/index.js
[source, javascript]
----
// directive install 정의
import custom from './custom';
import clickOutSide from './clickOutside';
import regex from './regex';
import authorization from './authorization';
import validation from './validation';

export default {
  install(Vue) {
    Vue.directive('custom', custom);
    Vue.directive('click-outside', clickOutSide);
    Vue.directive('regex', regex);
    Vue.directive('authorization', authorization);
    Vue.directive('validation', validation);
  },
};
----

.main.js
[source, javascript]
----
// directive 사용
// ... 생략 ...
import SdlDirectives from './directives';

app.use(SdlDirectives);
// ... 생략 ...
};
----

== filter
* Vue 에서 텍스트 형식화를 적용할 수 있는 필터를 정의한다.

NOTE: Vue3에선 전역 method 방식으로 사용한다.

./filters/index.js
[source, javascript]
----
// filter install 정의
import dateFormat from './dateFormat';
import numberFormat from './numberFormat';
import reverse from './reverse';
import nl2br from './nl2br';
import cutString from './cutString';

export default {
  install(Vue) {
    Vue.config.globalProperties.$filters = {
      reverse: reverse,
      dateFormat: dateFormat,
      numberFormat: numberFormat,
      nl2br: nl2br,
      cutString: cutString,
    };
  },
};
----

.예시
[source, html]
----
<span class="ui--text-total">
    <strong>Total</strong> {{ $filters.numberFormat(total) }}
</span>
----



== 다국어 세팅 위치 및 사용 방법
image::front_02_27.png[]
* vue-i18n을 통한 다국어 지원
* 서버단의 모든 message.properties를 읽어 사용자 토큰이 없을 경우에는 브라우져의 언어셋을 사용자 토큰이 있을 경우에는 지정된 언어셋으로 지정된다.
* vue-i18n에서 제공하는 $t를 이용하거나 SDL에서 제공하는 SDLUtil 유틸을 이용해서 다국어를 사용할 수 있다.

== 공통 component import 구조 및 사용 방법
image::front_02_28.png[]
SDL에서 제공하는 공통 컴포넌트를 src/components/common/control/index.js에 컴포넌트로 리스트업 후 src/main.js에서 최종 plugin 한다.

== 사용자 검색 팝업
image::front_02_29.png[]
사용자 조회 function으로 아래와 같은 param을 정의해 사용한다.
[source,javascript]
----
{
    searchColumn : '검색할 컬럼'(name : '이름', knoxId :'knoxId 아이디')
    searchTxt : '검색할 text'('like로 검색됨')
    rtnFunc : '검색한 내용을 return받을 function'
 }
----
