v0.1.27 - 달력 기준과 우측 패널 레이아웃 정리
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
- 프로젝트명: 10 Minute Planner 웹 UI
|
- 프로젝트명: 10 Minute Planner 웹 UI
|
||||||
- 기술 스택: Vue 3 + Vite + TailwindCSS + JavaScript
|
- 기술 스택: Vue 3 + Vite + TailwindCSS + JavaScript
|
||||||
- 현재 기준 버전: `v0.1.25` 준비 중
|
- 현재 기준 버전: `v0.1.27` 준비 중
|
||||||
- Git 원격 저장소: `https://git.sori.studio/zenn/planner.sori.studio.git`
|
- Git 원격 저장소: `https://git.sori.studio/zenn/planner.sori.studio.git`
|
||||||
|
|
||||||
## 기준 디자인
|
## 기준 디자인
|
||||||
@@ -164,6 +164,9 @@
|
|||||||
- 개발/배포 실행 방법은 루트 `README.md`에 먼저 적고, `HANDOFF.md`에는 변경 이유와 주의사항 위주로 남긴다.
|
- 개발/배포 실행 방법은 루트 `README.md`에 먼저 적고, `HANDOFF.md`에는 변경 이유와 주의사항 위주로 남긴다.
|
||||||
- API 클라이언트는 body가 없는 `GET`, `DELETE` 요청에 `Content-Type: application/json`을 붙이지 않도록 수정했다. 날짜 선택 시 발생하던 `Body cannot be empty...` 오류는 이 문제였다.
|
- API 클라이언트는 body가 없는 `GET`, `DELETE` 요청에 `Content-Type: application/json`을 붙이지 않도록 수정했다. 날짜 선택 시 발생하던 `Body cannot be empty...` 오류는 이 문제였다.
|
||||||
- 날짜 이동 중 목표 자동 보정으로 `goalEnabled`만 꺼지는 경우에는, 실제 내용이 없는 기록이라면 클라우드 동기화 토스트를 띄우지 않도록 정리했다.
|
- 날짜 이동 중 목표 자동 보정으로 `goalEnabled`만 꺼지는 경우에는, 실제 내용이 없는 기록이라면 클라우드 동기화 토스트를 띄우지 않도록 정리했다.
|
||||||
|
- 집중 보기에서 오른쪽 패널 폭을 넓혀 `1920x1080` 기준 활용도를 높였고, `TASK LABELS / D-DAY / CALENDAR`는 상단 고정 영역으로 올렸다.
|
||||||
|
- `STATS`와 `NEXT DAY`는 반반 카드가 아니라 각각 한 줄씩 쓰도록 바꿔서 날짜 길이에 따라 높이가 흔들리는 문제를 줄였다.
|
||||||
|
- 미니 달력은 42칸 기준으로 렌더링하고, 요일 헤더를 `SUN ~ SAT` 순서로 고정해서 일요일 시작 달력 기준을 더 명확하게 맞췄다.
|
||||||
- 비로그인 랜딩 카드는 상단 고정이 아니라 화면 중앙에 오도록 정렬을 수정했다.
|
- 비로그인 랜딩 카드는 상단 고정이 아니라 화면 중앙에 오도록 정렬을 수정했다.
|
||||||
- 현재 환경에서는 Docker 데몬이 꺼져 있어서 `docker compose build` 실검증은 하지 못했고, 데몬 시작 후 다시 확인이 필요하다.
|
- 현재 환경에서는 Docker 데몬이 꺼져 있어서 `docker compose build` 실검증은 하지 못했고, 데몬 시작 후 다시 확인이 필요하다.
|
||||||
- 이미지 저장 기능은 추후 `print-only` 또는 별도 export 전용 레이아웃을 기준으로 구현하면 화면/인쇄/공유 결과를 맞추기 쉽다.
|
- 이미지 저장 기능은 추후 `print-only` 또는 별도 export 전용 레이아웃을 기준으로 구현하면 화면/인쇄/공유 결과를 맞추기 쉽다.
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ten-minute-planner",
|
"name": "ten-minute-planner",
|
||||||
"version": "0.1.26",
|
"version": "0.1.27",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ten-minute-planner",
|
"name": "ten-minute-planner",
|
||||||
"version": "0.1.26",
|
"version": "0.1.27",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vue": "^3.5.13"
|
"vue": "^3.5.13"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ten-minute-planner",
|
"name": "ten-minute-planner",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.26",
|
"version": "0.1.27",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
176
src/App.vue
176
src/App.vue
@@ -314,7 +314,7 @@ const calendarDays = computed(() => {
|
|||||||
const start = new Date(first)
|
const start = new Date(first)
|
||||||
start.setDate(first.getDate() - first.getDay())
|
start.setDate(first.getDate() - first.getDay())
|
||||||
|
|
||||||
return Array.from({ length: 35 }, (_, index) => {
|
return Array.from({ length: 42 }, (_, index) => {
|
||||||
const date = new Date(start)
|
const date = new Date(start)
|
||||||
date.setDate(start.getDate() + index)
|
date.setDate(start.getDate() + index)
|
||||||
return {
|
return {
|
||||||
@@ -1522,7 +1522,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
v-else-if="screenMode === 'planner' && viewMode === 'focus'"
|
v-else-if="screenMode === 'planner' && viewMode === 'focus'"
|
||||||
class="print-hidden grid gap-6 xl:h-full xl:min-h-0 xl:grid-cols-[minmax(0,1fr)_340px]"
|
class="print-hidden grid gap-6 xl:h-full xl:min-h-0 xl:grid-cols-[minmax(0,1fr)_440px] 2xl:grid-cols-[minmax(0,1fr)_520px]"
|
||||||
>
|
>
|
||||||
<div class="scrollbar-hide print-target rounded-[28px] border border-white/60 bg-white/45 p-4 shadow-[0_18px_60px_rgba(28,25,23,0.06)] xl:h-full xl:min-h-0 xl:overflow-y-auto xl:pr-3">
|
<div class="scrollbar-hide print-target rounded-[28px] border border-white/60 bg-white/45 p-4 shadow-[0_18px_60px_rgba(28,25,23,0.06)] xl:h-full xl:min-h-0 xl:overflow-y-auto xl:pr-3">
|
||||||
<PlannerPage
|
<PlannerPage
|
||||||
@@ -1549,6 +1549,91 @@ onMounted(() => {
|
|||||||
|
|
||||||
<aside class="scrollbar-hide print-hidden rounded-[28px] border border-white/60 bg-white/50 p-3 shadow-[0_18px_60px_rgba(28,25,23,0.06)] xl:h-full xl:min-h-0 xl:overflow-y-auto">
|
<aside class="scrollbar-hide print-hidden rounded-[28px] border border-white/60 bg-white/50 p-3 shadow-[0_18px_60px_rgba(28,25,23,0.06)] xl:h-full xl:min-h-0 xl:overflow-y-auto">
|
||||||
<div class="flex flex-col gap-4 rounded-[22px] p-2">
|
<div class="flex flex-col gap-4 rounded-[22px] p-2">
|
||||||
|
<div class="sticky top-0 z-10 -mx-1 rounded-[26px] bg-[linear-gradient(180deg,rgba(245,241,233,0.98)_0%,rgba(245,241,233,0.94)_78%,rgba(245,241,233,0)_100%)] px-1 pb-4 pt-1 backdrop-blur-sm">
|
||||||
|
<div class="grid gap-4 2xl:grid-cols-2">
|
||||||
|
<section class="2xl:col-span-2">
|
||||||
|
<MiniCalendar
|
||||||
|
:month-label="monthLabel"
|
||||||
|
:year-label="yearLabel"
|
||||||
|
:days="calendarDays"
|
||||||
|
:selected-key="toKey(selectedDate)"
|
||||||
|
:marked-keys="markedDateKeys"
|
||||||
|
@shift-month="shiftCalendarMonth"
|
||||||
|
@shift-year="shiftCalendarYear"
|
||||||
|
@go-today="selectDate(new Date())"
|
||||||
|
@select="selectDate"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="rounded-[24px] border border-stone-200 bg-white/88 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
|
<div class="flex items-start justify-between gap-3">
|
||||||
|
<div>
|
||||||
|
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">TASK LABELS</p>
|
||||||
|
<p class="mt-2 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
||||||
|
ON이면 왼쪽 라벨을 01, 02 형태로 채우고 OFF이면 비워 둡니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="relative h-8 w-16 shrink-0 rounded-full transition-colors duration-300 ease-out"
|
||||||
|
:class="areTaskLabelsNumbered(planner) ? 'bg-stone-900' : 'bg-stone-300'"
|
||||||
|
@click="areTaskLabelsNumbered(planner) ? clearTaskLabels(planner) : fillTaskLabelsWithNumbers(planner)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="absolute left-1 top-1 h-6 w-6 transform-gpu rounded-full bg-white shadow-sm transition-transform duration-300 ease-out will-change-transform"
|
||||||
|
:class="areTaskLabelsNumbered(planner) ? 'translate-x-8' : 'translate-x-0'"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="rounded-[24px] border border-stone-200 bg-white/88 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
|
<div class="flex items-start justify-between gap-3">
|
||||||
|
<div>
|
||||||
|
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">D-DAY 사용</p>
|
||||||
|
<p class="mt-2 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
||||||
|
목표 검색과 기간 설정은 GOALS 화면에서 관리하고, 여기서는 현재 날짜에 D-DAY를 보여줄지 여부만 제어합니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="relative h-8 w-16 shrink-0 rounded-full transition-colors duration-300 ease-out disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
:class="planner.goalEnabled ? 'bg-stone-900' : 'bg-stone-300'"
|
||||||
|
:disabled="!hasActiveGoalForSelectedDate"
|
||||||
|
@click="updateGoalEnabled(planner, !planner.goalEnabled)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="absolute left-1 top-1 h-6 w-6 transform-gpu rounded-full bg-white shadow-sm transition-transform duration-300 ease-out will-change-transform"
|
||||||
|
:class="planner.goalEnabled ? 'translate-x-8' : 'translate-x-0'"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 space-y-3">
|
||||||
|
<div v-if="plannerGoal" class="rounded-2xl border border-stone-200 bg-white px-4 py-3">
|
||||||
|
<p class="text-[10px] font-bold tracking-[0.16em] text-stone-500">현재 목표</p>
|
||||||
|
<p class="mt-2 text-sm font-semibold tracking-[0.02em] text-stone-900">{{ plannerGoal.title }}</p>
|
||||||
|
<p class="mt-1 text-[11px] font-semibold tracking-[0.06em] text-stone-500">
|
||||||
|
목표일 {{ plannerGoal.targetDate }} / 적용 {{ plannerGoal.activeFrom }} ~ {{ plannerGoal.activeUntil }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="plannerGoal" class="rounded-2xl border border-stone-200 bg-[#fbf7f0] px-4 py-4">
|
||||||
|
<p class="text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
||||||
|
이 날짜에는 이미 적용된 목표가 있으므로 토글만으로 표시 여부를 빠르게 조절할 수 있습니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="rounded-2xl border border-dashed border-stone-300 bg-white/70 px-4 py-4">
|
||||||
|
<p class="text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-500">
|
||||||
|
현재 날짜에 적용된 목표가 없습니다. GOALS 화면에서 표시 기간을 지정하면 여기 토글이 자동으로 활성화됩니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
<p class="mb-4 text-[11px] font-bold tracking-[0.22em] text-ink">PREV SNAPSHOT</p>
|
<p class="mb-4 text-[11px] font-bold tracking-[0.22em] text-ink">PREV SNAPSHOT</p>
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
@@ -1562,28 +1647,6 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
|
||||||
<div class="flex items-start justify-between gap-3">
|
|
||||||
<div>
|
|
||||||
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">TASK LABELS</p>
|
|
||||||
<p class="mt-2 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
|
||||||
ON이면 왼쪽 라벨을 01, 02 형태로 채우고 OFF이면 비워 둡니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="relative h-8 w-16 shrink-0 rounded-full transition-colors duration-300 ease-out"
|
|
||||||
:class="areTaskLabelsNumbered(planner) ? 'bg-stone-900' : 'bg-stone-300'"
|
|
||||||
@click="areTaskLabelsNumbered(planner) ? clearTaskLabels(planner) : fillTaskLabelsWithNumbers(planner)"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="absolute left-1 top-1 h-6 w-6 transform-gpu rounded-full bg-white shadow-sm transition-transform duration-300 ease-out will-change-transform"
|
|
||||||
:class="areTaskLabelsNumbered(planner) ? 'translate-x-8' : 'translate-x-0'"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
<p class="mb-4 text-[11px] font-bold tracking-[0.22em] text-ink">READ NEXT</p>
|
<p class="mb-4 text-[11px] font-bold tracking-[0.22em] text-ink">READ NEXT</p>
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
@@ -1598,64 +1661,7 @@ onMounted(() => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
<div class="flex items-start justify-between gap-3">
|
<article>
|
||||||
<div>
|
|
||||||
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">D-DAY 사용</p>
|
|
||||||
<p class="mt-2 text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
|
||||||
목표 검색과 기간 설정은 GOALS 화면에서 관리하고, 여기서는 현재 날짜에 D-DAY를 보여줄지 여부만 제어합니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="relative h-8 w-16 shrink-0 rounded-full transition-colors duration-300 ease-out disabled:cursor-not-allowed disabled:opacity-50"
|
|
||||||
:class="planner.goalEnabled ? 'bg-stone-900' : 'bg-stone-300'"
|
|
||||||
:disabled="!hasActiveGoalForSelectedDate"
|
|
||||||
@click="updateGoalEnabled(planner, !planner.goalEnabled)"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="absolute left-1 top-1 h-6 w-6 transform-gpu rounded-full bg-white shadow-sm transition-transform duration-300 ease-out will-change-transform"
|
|
||||||
:class="planner.goalEnabled ? 'translate-x-8' : 'translate-x-0'"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4 space-y-3">
|
|
||||||
<div v-if="plannerGoal" class="rounded-2xl border border-stone-200 bg-white px-4 py-3">
|
|
||||||
<p class="text-[10px] font-bold tracking-[0.16em] text-stone-500">현재 목표</p>
|
|
||||||
<p class="mt-2 text-sm font-semibold tracking-[0.02em] text-stone-900">{{ plannerGoal.title }}</p>
|
|
||||||
<p class="mt-1 text-[11px] font-semibold tracking-[0.06em] text-stone-500">
|
|
||||||
목표일 {{ plannerGoal.targetDate }} / 적용 {{ plannerGoal.activeFrom }} ~ {{ plannerGoal.activeUntil }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="plannerGoal" class="rounded-2xl border border-stone-200 bg-[#fbf7f0] px-4 py-4">
|
|
||||||
<p class="text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-600">
|
|
||||||
이 날짜에는 이미 적용된 목표가 있으므로 토글만으로 표시 여부를 빠르게 조절할 수 있습니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="rounded-2xl border border-dashed border-stone-300 bg-white/70 px-4 py-4">
|
|
||||||
<p class="text-[11px] font-semibold leading-5 tracking-[0.06em] text-stone-500">
|
|
||||||
현재 날짜에 적용된 목표가 없습니다. GOALS 화면에서 표시 기간을 지정하면 여기 토글이 자동으로 활성화됩니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<MiniCalendar
|
|
||||||
:month-label="monthLabel"
|
|
||||||
:year-label="yearLabel"
|
|
||||||
:days="calendarDays"
|
|
||||||
:selected-key="toKey(selectedDate)"
|
|
||||||
:marked-keys="markedDateKeys"
|
|
||||||
@shift-month="shiftCalendarMonth"
|
|
||||||
@shift-year="shiftCalendarYear"
|
|
||||||
@go-today="selectDate(new Date())"
|
|
||||||
@select="selectDate"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<section class="grid grid-cols-2 gap-4">
|
|
||||||
<article class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
|
||||||
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">STATS</p>
|
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">STATS</p>
|
||||||
<div class="mt-5 space-y-4">
|
<div class="mt-5 space-y-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -1668,8 +1674,10 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
<article class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
<section class="rounded-[24px] border border-stone-200 bg-white/82 p-5 shadow-[0_12px_36px_rgba(28,25,23,0.05)]">
|
||||||
|
<article>
|
||||||
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">NEXT DAY</p>
|
<p class="text-[11px] font-bold tracking-[0.22em] text-ink">NEXT DAY</p>
|
||||||
<div class="mt-5 space-y-3">
|
<div class="mt-5 space-y-3">
|
||||||
<p class="text-lg font-semibold tracking-[-0.04em] text-stone-900">
|
<p class="text-lg font-semibold tracking-[-0.04em] text-stone-900">
|
||||||
@@ -1677,7 +1685,7 @@ onMounted(() => {
|
|||||||
<span class="ml-1" :class="secondaryDateDisplay.weekdayTone">{{ secondaryDateDisplay.weekday }}</span>
|
<span class="ml-1" :class="secondaryDateDisplay.weekdayTone">{{ secondaryDateDisplay.weekday }}</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-[11px] font-semibold tracking-[0.08em] text-stone-600">
|
<p class="text-[11px] font-semibold tracking-[0.08em] text-stone-600">
|
||||||
내일의 첫 작업은 "{{ secondaryPlanner.tasks[0]?.title || '새 작업 추가' }}" 로 시작합니다.
|
내일의 첫 작업은 "{{ secondaryPlanner.tasks.find((task) => task.title.trim())?.title || '새 작업 추가' }}" 로 시작합니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -117,7 +117,12 @@ function selectYear(year) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3 grid grid-cols-7 gap-2 text-center text-[10px] font-bold tracking-[0.12em] text-stone-400">
|
<div class="mb-3 grid grid-cols-7 gap-2 text-center text-[10px] font-bold tracking-[0.12em] text-stone-400">
|
||||||
<span v-for="weekday in ['S', 'M', 'T', 'W', 'T', 'F', 'S']" :key="weekday">{{ weekday }}</span>
|
<span
|
||||||
|
v-for="weekday in ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']"
|
||||||
|
:key="weekday"
|
||||||
|
>
|
||||||
|
{{ weekday }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-7 gap-2">
|
<div class="grid grid-cols-7 gap-2">
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user