🔧 UI 개선: 푸터 정리, X 아이콘, 스케줄 디자인 개선, min-width 설정
This commit is contained in:
parent
e2c1a6a774
commit
12c58c622e
5 changed files with 63 additions and 73 deletions
2
.env
2
.env
|
|
@ -2,7 +2,7 @@
|
||||||
DB_HOST=mariadb
|
DB_HOST=mariadb
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_USER=fromis9
|
DB_USER=fromis9
|
||||||
DB_PASSWORD=Xk9#mP2$vL7@nQ4w
|
DB_PASSWORD="Xk9#mP2\$vL7@nQ4w"
|
||||||
DB_NAME=fromis9
|
DB_NAME=fromis9
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,23 @@
|
||||||
import { Instagram, Youtube, Twitter } from 'lucide-react';
|
import { Instagram, Youtube } from 'lucide-react';
|
||||||
import { socialLinks } from '../../data/dummy';
|
import { socialLinks } from '../../data/dummy';
|
||||||
|
|
||||||
|
// X (Twitter) 아이콘 컴포넌트
|
||||||
|
const XIcon = ({ size = 24 }) => (
|
||||||
|
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
function Footer() {
|
function Footer() {
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-gray-900 text-white py-12">
|
<footer className="bg-gray-900 text-white py-12">
|
||||||
<div className="max-w-7xl mx-auto px-6">
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
<div className="grid grid-cols-3 gap-8">
|
<div className="grid grid-cols-3 gap-8">
|
||||||
{/* 로고 및 설명 */}
|
{/* 로고 */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-2xl font-bold text-primary-light mb-4">fromis_9</h3>
|
<h3 className="text-2xl font-bold text-primary-light mb-4">fromis_9</h3>
|
||||||
<p className="text-gray-400 text-sm leading-relaxed">
|
|
||||||
인사드리겠습니다. 둘, 셋!<br />
|
|
||||||
이제는 약속해 소중히 간직해,<br />
|
|
||||||
당신의 아이돌로 성장하겠습니다!<br />
|
|
||||||
안녕하세요, 프로미스나인입니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 링크 */}
|
{/* 링크 */}
|
||||||
|
|
@ -51,9 +54,9 @@ function Footer() {
|
||||||
href={socialLinks.twitter}
|
href={socialLinks.twitter}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-gray-400 hover:text-blue-400 transition-colors"
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
>
|
>
|
||||||
<Twitter size={24} />
|
<XIcon size={24} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -61,8 +64,7 @@ function Footer() {
|
||||||
|
|
||||||
{/* 저작권 */}
|
{/* 저작권 */}
|
||||||
<div className="border-t border-gray-800 mt-8 pt-8 text-center text-sm text-gray-500">
|
<div className="border-t border-gray-800 mt-8 pt-8 text-center text-sm text-gray-500">
|
||||||
<p>© 2025 fromis_9 Fan Site. This is an unofficial fan-made website.</p>
|
<p>© {currentYear} fromis_9 Fan Site. This is an unofficial fan-made website.</p>
|
||||||
<p className="mt-1">All rights belong to PLEDIS Entertainment / HYBE.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { Instagram, Youtube, Twitter } from 'lucide-react';
|
import { Instagram, Youtube } from 'lucide-react';
|
||||||
import { socialLinks } from '../../data/dummy';
|
import { socialLinks } from '../../data/dummy';
|
||||||
|
|
||||||
|
// X (Twitter) 아이콘 컴포넌트
|
||||||
|
const XIcon = ({ size = 20 }) => (
|
||||||
|
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
function Header() {
|
function Header() {
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ path: '/', label: '홈' },
|
{ path: '/', label: '홈' },
|
||||||
|
|
@ -58,9 +65,9 @@ function Header() {
|
||||||
href={socialLinks.twitter}
|
href={socialLinks.twitter}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-gray-500 hover:text-blue-500 transition-colors"
|
className="text-gray-500 hover:text-black transition-colors"
|
||||||
>
|
>
|
||||||
<Twitter size={20} />
|
<XIcon size={20} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ body {
|
||||||
color: #1a1a1a;
|
color: #1a1a1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 최소 너비 설정 - 화면 축소시 깨짐 방지 */
|
||||||
|
#root {
|
||||||
|
min-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 스크롤바 스타일 */
|
/* 스크롤바 스타일 */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { Calendar, Clock, MapPin, Users } from 'lucide-react';
|
import { Clock, MapPin, Users } from 'lucide-react';
|
||||||
import { schedules } from '../../data/dummy';
|
import { schedules } from '../../data/dummy';
|
||||||
|
|
||||||
function Schedule() {
|
function Schedule() {
|
||||||
|
|
@ -45,37 +45,27 @@ function Schedule() {
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 스케줄 타임라인 */}
|
{/* 스케줄 리스트 */}
|
||||||
<div className="max-w-4xl mx-auto">
|
<div className="max-w-4xl mx-auto space-y-4">
|
||||||
{Object.entries(groupedSchedules).map(([date, daySchedules], groupIndex) => {
|
{Object.entries(groupedSchedules).map(([date, daySchedules], groupIndex) => {
|
||||||
const formatted = formatDate(date);
|
const formatted = formatDate(date);
|
||||||
return (
|
return daySchedules.map((schedule, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={date}
|
|
||||||
initial={{ opacity: 0, x: -30 }}
|
|
||||||
animate={{ opacity: 1, x: 0 }}
|
|
||||||
transition={{ delay: groupIndex * 0.1 }}
|
|
||||||
className="relative pl-24 pb-12 last:pb-0"
|
|
||||||
>
|
|
||||||
{/* 타임라인 라인 */}
|
|
||||||
<div className="absolute left-[44px] top-0 bottom-0 w-0.5 bg-gray-200" />
|
|
||||||
|
|
||||||
{/* 날짜 원 */}
|
|
||||||
<div className="absolute left-0 top-0 w-[88px] flex items-start">
|
|
||||||
<div className="w-12 h-12 rounded-full bg-primary text-white flex flex-col items-center justify-center text-sm font-bold">
|
|
||||||
<span className="text-xs">{formatted.month}월</span>
|
|
||||||
<span>{formatted.day}</span>
|
|
||||||
</div>
|
|
||||||
<span className="ml-2 mt-3 text-sm text-gray-400">{formatted.weekday}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 스케줄 카드들 */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
{daySchedules.map((schedule, index) => (
|
|
||||||
<div
|
|
||||||
key={schedule.id}
|
key={schedule.id}
|
||||||
className="bg-white rounded-2xl p-6 shadow-md hover:shadow-lg transition-shadow"
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: (groupIndex * daySchedules.length + index) * 0.1 }}
|
||||||
|
className="flex items-stretch bg-white rounded-2xl shadow-sm hover:shadow-md transition-shadow overflow-hidden"
|
||||||
>
|
>
|
||||||
|
{/* 날짜 영역 */}
|
||||||
|
<div className="w-24 bg-primary flex flex-col items-center justify-center text-white py-6">
|
||||||
|
<span className="text-sm font-medium opacity-80">{formatted.month}월</span>
|
||||||
|
<span className="text-3xl font-bold">{formatted.day}</span>
|
||||||
|
<span className="text-sm font-medium opacity-80">{formatted.weekday}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 스케줄 내용 */}
|
||||||
|
<div className="flex-1 p-6">
|
||||||
<h3 className="font-bold text-lg mb-3">{schedule.title}</h3>
|
<h3 className="font-bold text-lg mb-3">{schedule.title}</h3>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-4 text-sm text-gray-500">
|
<div className="flex flex-wrap gap-4 text-sm text-gray-500">
|
||||||
|
|
@ -93,31 +83,17 @@ function Schedule() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
));
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 빈 스케줄 메시지 (스케줄이 없을 때) */}
|
{/* 빈 스케줄 메시지 */}
|
||||||
{Object.keys(groupedSchedules).length === 0 && (
|
{Object.keys(groupedSchedules).length === 0 && (
|
||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<Calendar size={64} className="mx-auto text-gray-300 mb-4" />
|
|
||||||
<p className="text-gray-500">예정된 스케줄이 없습니다.</p>
|
<p className="text-gray-500">예정된 스케줄이 없습니다.</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 안내 */}
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 30 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ delay: 0.5 }}
|
|
||||||
className="mt-12 bg-gray-50 rounded-2xl p-6 text-center text-sm text-gray-500"
|
|
||||||
>
|
|
||||||
<p>스케줄은 DC Inside 갤러리에서 자동으로 수집됩니다.</p>
|
|
||||||
<p className="mt-1">일정은 변경될 수 있으니 공식 채널을 확인해 주세요.</p>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue