인앱 미니 블로그(AI 자동 포스트, 이메일 승인)·이용후기(즉시 게시)·예약 요청(메일 발송)을
새로 붙였고, 병행해서 /s/stay 목업과 발행 사이트 공통 렌더러(UnitsSection·FestivalSection·
LocalGuideSection·WeatherSection 등)의 UI 버그를 다수 고쳤다. 범위가 넓지만 한 주 분량
작업을 한 커밋으로 묶어 달라는 요청에 따라 하나로 묶는다.
- solution/backend: post/review/booking_request 라우터·서비스·CRUD 추가, 스케줄러에
블로그 초안 생성(새벽 4:10)·발송(아침 9:00) cron 등록, 마이그레이션 4건 추가
- solution/frontend, admin/frontend: 생성된 API 클라이언트 갱신, 리뷰 모더레이션·
블로그 글 관리 페이지 추가
- solution/site/src: 객실 상세+실시간예약(날짜선택·연락처 폼)을 모달로 통합, 축제·
주변안내 카드 클릭 시 모달 전환, 후기 목록 카드 UI, 공용 Modal 컴포넌트 신설,
날씨 문구 동기화 버그 수정(하늘줄·기온줄 한 타이머로), 시설·편의 가능/불가 아이콘
색상 하이라이트, 헤더 메뉴 순서를 실제 섹션 순서에 맞춤, 하단 탭바 아이콘 정렬 버그
(line-height) 수정, 추천일정 점선 연결+데스크톱 자동펼침/모바일 축소, 채널 라벨에
크롤링 원문("NOL")이 새던 것을 bookingLabel() 로 교체
- solution/site/scripts/mockup: /s/stay 패치 스크립트·주입 CSS·JS 다수 수정, stay4~6
빌드 스크립트 추가(다른 세션 작업)
테스트: solution/site `npx tsc --noEmit` 통과, `npx vitest run` 93 passed,
solution/backend `pytest tests/test_booking_request.py` 6 passed(로컬 DB 대상).
예약 요청 메일은 실제 발송까지 확인(place 66894a1b 소유자 이메일 누락을 DB에서 보정).
185 lines
5.4 KiB
SCSS
185 lines
5.4 KiB
SCSS
@import 'libs/vars';
|
|
@import 'libs/functions';
|
|
@import 'libs/mixins';
|
|
@import 'libs/vendor';
|
|
@import 'libs/breakpoints';
|
|
@import 'libs/html-grid';
|
|
@import 'fontawesome-all.min.css';
|
|
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i');
|
|
|
|
/*
|
|
Story by HTML5 UP
|
|
html5up.net | @ajlkn
|
|
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
|
*/
|
|
|
|
// Breakpoints.
|
|
|
|
@include breakpoints((
|
|
xlarge: ( 1281px, 1680px ),
|
|
large: ( 981px, 1280px ),
|
|
medium: ( 737px, 980px ),
|
|
small: ( 481px, 736px ),
|
|
xsmall: ( 361px, 480px ),
|
|
xxsmall: ( null, 360px )
|
|
));
|
|
|
|
// Mixins.
|
|
|
|
@mixin color($p) {
|
|
@include color-typography($p);
|
|
@include color-box($p);
|
|
@include color-button($p);
|
|
@include color-form($p);
|
|
@include color-icon($p);
|
|
@include color-list($p);
|
|
@include color-section($p);
|
|
@include color-table($p);
|
|
@include color-banner($p);
|
|
@include color-spotlight($p);
|
|
@include color-gallery($p);
|
|
@include color-items($p);
|
|
@include color-index($p);
|
|
}
|
|
|
|
// Phone.
|
|
|
|
@mixin phone($image-width) {
|
|
@include vendor('flex-grow', '0');
|
|
@include vendor('flex-shrink', '0');
|
|
border-radius: 0;
|
|
border: solid _size(border-width);
|
|
|
|
img {
|
|
@include vendor('object-fit', 'cover');
|
|
@include vendor('object-position', 'center');
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 0;
|
|
}
|
|
|
|
&:before {
|
|
content: '';
|
|
display: block;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
border: solid _size(border-width);
|
|
border-bottom: 0;
|
|
}
|
|
|
|
&:after {
|
|
content: '';
|
|
display: block;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
border: solid _size(border-width);
|
|
border-top: 0;
|
|
}
|
|
|
|
@include resize-phone($image-width, 1);
|
|
}
|
|
|
|
@mixin resize-phone($image-width, $image-factor) {
|
|
$image-pad-top: 2.5rem;
|
|
$image-pad-bottom: 3rem;
|
|
$image-height: ($image-width * (1920 / 1080));
|
|
|
|
width: ($image-width * $image-factor);
|
|
height: (($image-width * $image-factor) * (1920 / 1080));
|
|
margin-top: ($image-pad-top * $image-factor);
|
|
margin-bottom: (_size(element-margin) + ($image-pad-bottom * $image-factor));
|
|
|
|
&:before {
|
|
height: ($image-pad-top * $image-factor);
|
|
background-size: (64px * $image-factor) (32px * $image-factor);
|
|
margin-top: (($image-pad-top * $image-factor) * -1);
|
|
border-radius: (1rem * $image-factor) (1rem * $image-factor) 0 0;
|
|
}
|
|
|
|
&:after {
|
|
height: ($image-pad-bottom * $image-factor);
|
|
background-size: (64px * $image-factor) (32px * $image-factor);
|
|
margin-bottom: (($image-pad-bottom * $image-factor) * -1);
|
|
border-radius: 0 0 (1rem * $image-factor) (1rem * $image-factor);
|
|
}
|
|
}
|
|
|
|
@mixin color-phone($p) {
|
|
border-color: _palette($p, border);
|
|
background-color: _palette($p, border);
|
|
|
|
@if ($p != 'invert') {
|
|
border-width: 0;
|
|
}
|
|
@else {
|
|
border-width: _size(border-width);
|
|
}
|
|
|
|
&:before {
|
|
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="32px" viewBox="0 0 64 32" zoomAndPan="disable"><style>rect {fill: transparent; stroke: #{_palette($p, border)}; stroke-width: #{_size(border-width)}; }</style><rect rx="4" ry="4" x="11" y="12" width="42" height="8" vector-effect="non-scaling-stroke" /></svg>');
|
|
border-color: _palette($p, border);
|
|
|
|
@if ($p == 'invert') {
|
|
width: calc(100% + #{_size(border-width) * 2});
|
|
margin-left: (_size(border-width) * -1);
|
|
}
|
|
@else {
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
&:after {
|
|
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="32px" viewBox="0 0 64 32" zoomAndPan="disable"><style>circle {fill: transparent; stroke: #{_palette($p, border)}; stroke-width: #{_size(border-width)}; }</style><circle cx="32" cy="16" r="14" vector-effect="non-scaling-stroke" /></svg>');
|
|
border-color: _palette($p, border);
|
|
|
|
@if ($p == 'invert') {
|
|
width: calc(100% + #{_size(border-width) * 2});
|
|
margin-left: (_size(border-width) * -1);
|
|
}
|
|
@else {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin color-phone-variant($v, $p) {
|
|
@if ($v == 'android') {
|
|
&:after {
|
|
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="32px" viewBox="0 0 64 32" zoomAndPan="disable"><style>rect {fill: transparent; stroke: #{_palette($p, border)}; stroke-width: #{_size(border-width)}; }</style><rect rx="4" ry="4" x="6" y="4" width="52" height="24" vector-effect="non-scaling-stroke" /></svg>');
|
|
}
|
|
}
|
|
@else if ($p == 'iphone') {
|
|
// ...
|
|
}
|
|
}
|
|
|
|
// Base.
|
|
|
|
@import 'base/reset';
|
|
@import 'base/page';
|
|
@import 'base/typography';
|
|
|
|
// Component.
|
|
|
|
@import 'components/row';
|
|
@import 'components/box';
|
|
@import 'components/button';
|
|
@import 'components/form';
|
|
@import 'components/icon';
|
|
@import 'components/image';
|
|
@import 'components/list';
|
|
@import 'components/actions';
|
|
@import 'components/icons';
|
|
@import 'components/section';
|
|
@import 'components/table';
|
|
@import 'components/banner';
|
|
@import 'components/spotlight';
|
|
@import 'components/gallery';
|
|
@import 'components/wrapper';
|
|
@import 'components/items';
|
|
@import 'components/index';
|
|
|
|
// Layout.
|
|
|
|
@import 'layout/wrapper'; |