[注釈]アプリケーション構成

28252 ワード

console.log('app is running!');

// let setLoading;

// TODO
// request 에러 처리
// jest test 만들기
// 슬라이드 만들기 => 만들긴 했는데...
// -case1 이미지 요청 계속x,
// -case2 배열 갯수만큼 index뽑아서 만드는 건데 다음,
// -case3 트랜지션이랑 픽셀 단위로 움직이게 만들기 해보기
// data 옵젝트 통일되게 사용하기 => data= { cats: [], isErr: false, payload: object } 이런 식으로
// 에러 페이지 컴포넌트를 만들어서 에러 나오면 해당 섹션에 뿌려주는 것 만들기

class App {
	$target = null;
	data = [];

	constructor($target) {
		this.$target = $target;

		// TODO: 새로고침 후 마지막 검색결과 불러와 보여주기 체크
		this.data = CatUtil.getObjfromLocal('data') || [];

		this.themeCheckbox = new ThemeCheckbox({
			$target,
		});

		// Loader를 생성하고 loader 내에 있는 setState를 api 호출 시 넘겨주고 이를 활용해 로딩 창 관리
		this.setLoading = (visible) => this.loader.setState({ visible });
		window.setLoading = this.setLoading; // window에서 관리?
		// setLoading = this.setLoading; // 아니면 변수로 관리?
		this.loader = new Loader({
			$target,
			setLoading: this.setLoading,
			data: {
				visible: false,
			},
		});

		// 서치 컴포넌트
		this.searchInput = new SearchInput({
			$target,
			onSearch: (keyword) => {
				this.searchResult.images.clear();
				this.onSearch(keyword, false, true);
			},
			updateKeywords: (keyword) => {
				const { keywords } = this.keywords.data;
				keywords.length >= 5 &&
					keywords.indexOf(keyword) == -1 &&
					keywords.shift();

				keywords.indexOf(keyword) == -1 &&
					this.keywords.setState({
						keywords: [...keywords, keyword],
					});
			},
		});

		// random 검색 버튼
		this.searchRandom = new SearchRandom({
			$target,
			onRandom: (isClear) => {
				this.searchResult.images.clear();
				this.onSearch(undefined, true, isClear);
			},
		});

		this.keywords = new Keywords({
			$target,
			data: {
				keywords: ['노르웨이', '먼치킨', '숲', '터키시', '샴'],
			},
			onSearch: (keyword) => {
				this.searchResult.images.clear();
				this.onSearch(keyword, false, true);
			},
		});

		this.banner = new Banner({
			$target,
			data: [],
		});

		this.searchResult = new SearchResult({
			$target,
			initialData: this.data,
			onRandom: () => this.onSearch(undefined, true),
			onClick: async (image) => {
				// TODO
				// promise로 넘어 온다 그런데 await하면 promise가 완료되고 값을 리턴해준다 {data: {...}}
				const { data } = await api.getCat(image.id);
				console.log('onClick > imageInfo', data);
				this.imageInfo.setState({
					visible: true,
					image: {
						...image,
						...data,
					},
				});
			},
		});

		this.imageInfo = new ImageInfo({
			$target,
			data: {
				visible: false,
				image: null,
			},
		});

		this.getBanner();

		// CatUtil.applyLazyLoading([...document.querySelectorAll('img.lazy')]);

		console.log('[CREATED]', 'App', this, this['loader'], this.loader);
	}

	onSearch = async (keyword, isRandom = false, isClear = false) => {
		if (isClear) this.searchResult.clearResults();

		this.searchResult.setIsRequesting(true);
		let result = null;
		if (isRandom) {
			result = await api.getRandom();
			console.log('App > onSearch:Random >', result);
		} else {
			result = await api.fetchCats(keyword);
			console.log('App > onSearch >', result);
		}
		this.searchResult.setIsRequesting(false);

		if (result.isErr)
			return alert(result.data.status + ': ' + result.data.message);
		else CatUtil.setObjtoLocal('data', result.data);

		this.setState(result.data);
	};

	getBanner = async () => {
		let tries = 3;
		let data;
		while (tries > 0) {
			const result = await api.getRandom();
			data = result.data;
			console.log(
				'!!! getBanner > tries',
				tries,
				result,
				result && result.data.length
			);
			if (data && data.length != undefined) break;
			tries--;
		}
		this.banner.setState(data);
	};

	setState = (nextData) => {
		// console.log(this);
		this.data = nextData; // App 업데이트 하고
		this.searchResult.setState(nextData); // SearchResult 업데이트 하고
	};
}