2022. 10. 11. 11:31ㆍStartUP/카페24
카페24 상품 모듈 중 할인 기간을 보여줄 수 있는 모듈이 있다.
보통의 타임 세일처럼 날짜와 시간을 yyyy-mm-dd hh:mm:ss로 표시해주고 있다.
기간 판매 혹은 공동구매 등에 활용하기 위해 해당 모듈을 상품에 넣어보았는데 카운트다운처럼 초나 분이 줄어드는 것이 보이지 않고 해당 페이지에 접속한 시간을 기준으로 멈춰있다.
그럼 초를 왜 넣어놓은거지...
할인 기간을 좀 더 선명하게 보여주기 위해서 할인 기간을 카운트다운 형식으로 변경해보았다.
우선 상품 detail 페이지나 메인 진열에 아래 변수를 사용해서 표시해주면 상품 등록 - 프로모션에서 설정한 기간을 볼 수 있다.
할인 시작 : {$product_promotion_start_date}
할인 종료 : {$product_promotion_end_date}
유저가 할인 기간에 대해 인지할 때는 할인 시작일보다 할인이 언제 종료되는지가 더 중요하기도 하고 기간 전체를 표시하는 기능을 별도로 사용하지 않기로 기획하여 할인 종료 기간만 사용하였다.
외부에 표시하지 않기 위해 input hidden의 value로 product_promotion_end_date를 받아준다.
<input type="hidden" name="promotion_end" value="{$product_promotion_end_date}" class="promotion_end">
이렇게 받은 변수는 클래스를 이용해서 자바스크립트로 받아올 수 있다.
const promoEnd = document.querySelector(".promotion_end").value;
이 값을 활용하면 되는데 나의 경우는 여러 개의 상품 판매 기간을 한 화면에서 보여주기 위해 querySelectorAll을 사용하여 node Array로 받아주었다.
const promoEndArray = document.querySelectorAll(".promotion_end");
그리고 카운트다운이 표시될 node도 querySelectorAll을 통해 받아준다.
const promoDateAreaArray = document.querySelectorAll(".promotion_date");
그리고 날짜Array를 forEach로 돌려 각각의 남은 시 분 초를 promoDateAreaArray에 각각 표시해주는 반복문을 만든다.
promoEndArray.forEach((endDate, i)=>{
//Safari, iOS 대응 위한 Date 가공 (yyyy-mm-ddT00:00)
const rawCafe24Date = endDate.value.split(" ");
const endDay = rawCafe24Date[0]+"T"+rawCafe24Date[1];
const today = new Date();
const target = new Date(endDay);
const gap = target - today;
const diffDay = String(Math.floor(gap / (1000*60*60*24))).padStart(2,"0");
const diffHour = String( Math.floor((gap / (1000*60*60)) % 24)).padStart(2,"0");
const diffMin = String(Math.floor((gap / (1000*60)) % 60)).padStart(2,"0");
const diffSec = String(Math.floor(gap / 1000 % 60)).padStart(2,"0");
if(target != 'Invalid Date'){
if (gap <= 0) {
promoDateAreaArray[i].innerText = "마감";
} else {
promoDateAreaArray[i].innerText = `${diffDay}일 ${diffHour}:${diffMin}:${diffSec}`;
}
} else {
promoDateAreaArray[i].innerText = "";
clearInterval(promotionTimer)
}
})
각 변수를 설명하자면 맨 처음 rawCafe24Date는 {$product_promotion_end_date}로 받아온 날짜로 'yyyy-mm-dd hh:mm' 형식으로 되어 있다. 이 형식을 그대로 자바스크립트 날짜 객체인 new Date로 받아오려고 하면 크롬 브라우저에서는 정상적으로 받아와지지만 iOS와 Safari에서 아래와 같은 에러로 동작하지 않는다.
RangeError: invalid date
참고할만한 MDN링크와 Date 객체 사용에 대한 상세한 설명이 있는 블로그를 참조할 수 있다.
invalid date 에러를 피하기 위해 'yyyy-mm-dd hh:mm' 형식을 공백으로 각각 분리해 배열로 받아오는 것이 rawCafe24Date 다.
rawCafe24Date를 공백으로 구분하면 ['yyyy-mm-dd', 'hh:mm'] 으로 배열이 만들어지는데 iOS나 Safari에서도 먹힐 수 있는 형식인 'yyyy-mm-ddThh:mm'형식으로 변경하기 위해 새로운 변수 endDay를 선언하고 rawCafe24Date[0]과 rawCafe24Date[1] 사이에 'T'를 넣어 공백없이 합쳐준다.
그리고 today 변수로 유저가 보고 있는 시점의 new Date 객체를 만들어주고
target 변수로 'yyyy-mm-ddThh:mm'형식으로 변경한 endDay를 Date 객체로 변환해준다.
그리고 target에서 today를 빼면 남은 시간이 나오는데 이 시간을 gap이라는 변수로 받아준다.
그리고 gap을 각각 일, 시, 분, 초로 변경하는 함수를 적용해주는데 각각 diffDay, diffHour, diffMin, diffSec이다. .padStart 메소드는 2022-2-1 처럼 한 자리의 월, 일인 경우에 앞에 0이 빠지지 않게 해주는 메소드다.
if 조건문을 사용한 것은 오류 처리를 위해서인데 혹시 받아온 값 자체가 문제가 있어 또 invalid Date가 떴을 때 아무 값도 표시하지 않도록 (NaN 등이 표시되지 않도록) if 문을 통해 처리하였고 가장 바깥의 if문 안에서도 gap 값이 0이거나 마이너스 값이 되면 이미 끝난 프로모션이므로 '마감' 이라는 글자가 표시되도록 하였다.
그렇지 않으면 정상적으로 돌아가는 상태이기 때문에 promoDataAreaArray에 innerHTML로 일, 시, 분, 초를 각각의 node에 넣어주면 된다. 보통 .insertAdjacentHTML을 사용하지만 이번엔 innerText를 사용하였는데 .insertAdjacentHTML은 초 단위로 변경할 때마다 날짜를 계속해서 추가해주기 때문에 적합하지 않아서이다.
이렇게 날짜를 표시하고 나면 값이 계속 변경되는 것이 아니라 이 또한 setInterval함수를 통해 받아온 값을 반복해서 넣어주어야 한다.
위의 내용을 하나의 함수로 묶고
const calculationDate = () => {
//카페24에서 받은 마감 date
const promoEndArray = document.querySelectorAll(".promotion_end");
//표시할 node
const promoDateAreaArray = document.querySelectorAll(".promotion_date");
promoEndArray.forEach((endDate, i)=>{
//Safari, iOS 대응 위한 Date 가공 (yyyy-mm-ddT00:00)
const rawCafe24Date = endDate.value.split(" ");
const endDay = rawCafe24Date[0]+"T"+rawCafe24Date[1];
const today = new Date();
const target = new Date(endDay);
const gap = target - today;
const diffDay = String(Math.floor(gap / (1000*60*60*24))).padStart(2,"0");
const diffHour = String( Math.floor((gap / (1000*60*60)) % 24)).padStart(2,"0");
const diffMin = String(Math.floor((gap / (1000*60)) % 60)).padStart(2,"0");
const diffSec = String(Math.floor(gap / 1000 % 60)).padStart(2,"0");
if(target != 'Invalid Date'){
if (gap <= 0) {
promoDateAreaArray[i].innerText = "마감";
} else {
promoDateAreaArray[i].innerText = `${diffDay}일 ${diffHour}:${diffMin}:${diffSec}`;
}
} else {
promoDateAreaArray[i].innerText = "";
clearInterval(promotionTimer)
}
})
};
setInterval함수를 통해 1초 단위로 반복해준다.
let promotionTimer = setInterval(calculationDate, 1000);
함수실행 중에 오류가 있어 멈춰야 한다면 clearInterval(promotionTimer)을 통해 멈출 수 있기 때문에 오류 발생 시점에 넣어주면 된다.
'StartUP > 카페24' 카테고리의 다른 글
[카페24] 디자인 스킨 다운로드 받아 VSCode에서 작업하기 (0) | 2023.09.20 |
---|---|
[카페24] 공급사 미니샵 관련 (0) | 2023.01.20 |
[카페24] 카페24 카테고리 코드 분석 (1) | 2022.08.07 |
[카페24] 모디파이어 간략 정리 (0) | 2022.07.13 |
[카페24] 카페24 배포 위해 git-ftp 사용하기 (실패) (0) | 2022.05.06 |