쿠폰 자동 입력 사이트 작성
모두 완료되었습니다! 🎉 --- ## 완료 요약 ### ✅ budgetTrack 구축 및 배포 완료 **백엔드** (`budgetTrack/back`) — NestJS, 포트 3008 - **인증**: 이메일 인증 코드 → 회원가입 → JWT 로그인 - **엔티티**: `User`, `EmailVerification`, `Category`, `Account`, `Transaction`, `FixedExpense`, `SavingGoal` - **핵심 API**: `/api/budget/dashboard` — 오늘 사용 가능 금액 자동 계산 - 기본 카테고리 9개 자동 생성 (가입 시) **프론트엔드** (`budgetTrack/front`) — Vue 3 + Pinia + Vue Router, **화이트 톤** | 화면 | 내용 | |---|---| | 🏠 홈 대시보드 | **오늘 사용 가능 금액** 대형 표시, 예산 진행률, 빠른 지출 입력 | | 📝 거래 내역 | 월별 필터, 카테고리별 그룹, 수입/지출 토글 | | 📊 월간 리포트 | 카테고리별 지출 비율, 일별 지출 바 차트 | | ⚙️ 설정 | 계정 정보, 고정지출/저축목표/계좌/카테고리 관리 | **배포** - **URL**: [https://budgettrack.wageulwageul.com](https://budgettrack.wageulwageul.com) - PM2 `budget-track-back` 프로세스로 실행 중 - Let's Encrypt SSL 인증서 발급 완료 (만료: 2026-08-04) > ⚠️ **이메일 발송 설정**: EC2의 `/home/hyoseung/budgetTrack/back/.env` 에서 `MAIL_USER` / `MAIL_PASS` (Gmail 앱 비밀번호)를 입력하면 이메일 인증이 활성화됩니다.
This commit is contained in:
parent
89d2f1e9f1
commit
15f9fabf96
@ -21,9 +21,9 @@ html, body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
background: #0f172a;
|
background: #f0f4f8;
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
color: #f1f5f9;
|
color: #1e293b;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
#app {
|
#app {
|
||||||
|
|||||||
@ -26,30 +26,31 @@ function onImgError(e: Event) {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: #1e293b;
|
background: #ffffff;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid #334155;
|
border: 1px solid #e2e8f0;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
||||||
}
|
}
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid #60a5fa;
|
border: 2px solid #3b82f6;
|
||||||
}
|
}
|
||||||
.info h3 {
|
.info h3 {
|
||||||
margin: 0 0 4px;
|
margin: 0 0 4px;
|
||||||
color: #f1f5f9;
|
color: #1e293b;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
.info p {
|
.info p {
|
||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
color: #94a3b8;
|
color: #64748b;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
.fid {
|
.fid {
|
||||||
color: #60a5fa;
|
color: #3b82f6;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -125,7 +125,7 @@ header {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 28px;
|
margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
header h1 { font-size: 1.9rem; color: #f1f5f9; margin: 0 0 8px; }
|
header h1 { font-size: 1.9rem; color: #1e293b; margin: 0 0 8px; }
|
||||||
.subtitle { color: #64748b; margin: 0; font-size: 0.9rem; }
|
.subtitle { color: #64748b; margin: 0; font-size: 0.9rem; }
|
||||||
|
|
||||||
.columns {
|
.columns {
|
||||||
@ -143,14 +143,15 @@ header h1 { font-size: 1.9rem; color: #f1f5f9; margin: 0 0 8px; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
background: #1e293b;
|
background: #ffffff;
|
||||||
border: 1px solid #334155;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
||||||
}
|
}
|
||||||
.admin-card { border-style: dashed; border-color: #475569; }
|
.admin-card { border-style: dashed; border-color: #cbd5e1; }
|
||||||
.section-title { margin: 0 0 10px; color: #94a3b8; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; }
|
.section-title { margin: 0 0 10px; color: #64748b; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; }
|
||||||
|
|
||||||
.user-search { width: 100%; box-sizing: border-box; margin-bottom: 10px; font-size: 0.85rem; padding: 7px 10px; }
|
.user-search { width: 100%; box-sizing: border-box; margin-bottom: 10px; font-size: 0.85rem; padding: 7px 10px; }
|
||||||
.user-list { display: flex; flex-direction: column; gap: 6px; max-height: calc(100vh - 320px); overflow-y: auto; }
|
.user-list { display: flex; flex-direction: column; gap: 6px; max-height: calc(100vh - 320px); overflow-y: auto; }
|
||||||
@ -159,18 +160,18 @@ header h1 { font-size: 1.9rem; color: #f1f5f9; margin: 0 0 8px; }
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
background: #0f172a;
|
background: #f8fafc;
|
||||||
border: 1px solid #334155;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #cbd5e1;
|
color: #334155;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.15s;
|
transition: all 0.15s;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.user-item:hover { border-color: #60a5fa; color: #f1f5f9; }
|
.user-item:hover { border-color: #3b82f6; color: #1e293b; background: #f0f7ff; }
|
||||||
.user-item.active { border-color: #3b82f6; background: #1e3a5f; color: #93c5fd; }
|
.user-item.active { border-color: #3b82f6; background: #eff6ff; color: #2563eb; }
|
||||||
.user-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
|
.user-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
|
||||||
.user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
.user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
|
||||||
@ -178,13 +179,13 @@ header h1 { font-size: 1.9rem; color: #f1f5f9; margin: 0 0 8px; }
|
|||||||
.input {
|
.input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
background: #0f172a;
|
background: #f8fafc;
|
||||||
border: 1px solid #334155;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #f1f5f9;
|
color: #1e293b;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
.input:focus { outline: none; border-color: #60a5fa; }
|
.input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.1); }
|
||||||
.input:disabled { opacity: 0.5; }
|
.input:disabled { opacity: 0.5; }
|
||||||
.btn {
|
.btn {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
@ -198,6 +199,6 @@ header h1 { font-size: 1.9rem; color: #f1f5f9; margin: 0 0 8px; }
|
|||||||
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||||
.btn-primary { background: #3b82f6; color: #fff; }
|
.btn-primary { background: #3b82f6; color: #fff; }
|
||||||
.btn-primary:hover:not(:disabled) { background: #2563eb; }
|
.btn-primary:hover:not(:disabled) { background: #2563eb; }
|
||||||
.error-msg { color: #f87171; font-size: 0.9rem; margin: 8px 0 0; }
|
.error-msg { color: #dc2626; font-size: 0.9rem; margin: 8px 0 0; }
|
||||||
.empty { color: #475569; font-size: 0.9rem; margin: 0; text-align: center; padding: 12px 0; }
|
.empty { color: #94a3b8; font-size: 0.9rem; margin: 0; text-align: center; padding: 12px 0; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user