AdminLTE3
This commit is contained in:
374
.history/views/LandingDemo_20251026205940.tsx
Normal file
374
.history/views/LandingDemo_20251026205940.tsx
Normal file
@@ -0,0 +1,374 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
ArrowRight, Calculator, Code2, Smartphone, Palette, LineChart, Eye, Menu, X,
|
||||
Sun, Moon, ChevronDown, Phone, Mail, MessageCircle, Rocket, Users, Clock,
|
||||
Headphones, Award
|
||||
} from "lucide-react";
|
||||
import AOS from "aos";
|
||||
import "aos/dist/aos.css";
|
||||
|
||||
// Korean i18n strings to replace <%- __('...') %>
|
||||
const t = {
|
||||
navigation: {
|
||||
home: "홈",
|
||||
about: "회사소개",
|
||||
services: "서비스",
|
||||
portfolio: "포트폴리오",
|
||||
contact: "연락처",
|
||||
calculator: "비용계산기"
|
||||
},
|
||||
language: {
|
||||
korean: "한국어",
|
||||
english: "English",
|
||||
russian: "Русский",
|
||||
kazakh: "Қазақша"
|
||||
},
|
||||
hero: {
|
||||
title: { smart: "스마트", solutions: "솔루션" },
|
||||
subtitle: "혁신적인 기술로 비즈니스를 성장시키세요",
|
||||
description: "비즈니스의 디지털 전환을 이끄는 혁신적인 웹개발, 모바일 앱, UI/UX 디자인",
|
||||
cta: { start: "시작하기", portfolio: "포트폴리오 보기" },
|
||||
},
|
||||
services: {
|
||||
title: { our: "우리의", services: "서비스" },
|
||||
subtitle: "아이디어를 현실로 만드는 전문 개발 서비스",
|
||||
description: "최첨단 기술과 창의적 아이디어로 완성하는 디지털 솔루션",
|
||||
view_all: "모든 서비스 보기",
|
||||
web: { title: "웹 개발", description: "반응형 웹사이트 및 웹 애플리케이션 개발", price: "500,000원부터" },
|
||||
mobile: { title: "모바일 앱", description: "iOS 및 Android 네이티브 앱 개발", price: "1,000,000원부터" },
|
||||
design: { title: "UI/UX 디자인", description: "사용자 중심의 인터페이스 및 경험 디자인", price: "300,000원부터" },
|
||||
marketing: { title: "디지털 마케팅", description: "SEO, 소셜미디어 마케팅, 광고 관리", price: "200,000원부터" },
|
||||
hero: {
|
||||
title: "우리의",
|
||||
title_highlight: "서비스",
|
||||
subtitle: "혁신적인 기술로 비즈니스 성장 지원"
|
||||
},
|
||||
cards: {
|
||||
starting_price: "시작 가격",
|
||||
consultation: "상담",
|
||||
calculate_cost: "비용 계산",
|
||||
popular: "인기"
|
||||
},
|
||||
process: {
|
||||
title: "프로젝트 수행 과정",
|
||||
subtitle: "체계적이고 전문적인 프로세스로 프로젝트를 진행합니다",
|
||||
step1: { title: "상담 및 기획", description: "고객의 요구사항을 정확히 파악하고 최적의 솔루션을 기획합니다" },
|
||||
step2: { title: "디자인 및 설계", description: "사용자 중심의 직관적인 디자인과 견고한 시스템 아키텍처를 설계합니다" },
|
||||
step3: { title: "개발 및 구현", description: "최신 기술과 모범 사례를 활용하여 효율적이고 확장 가능한 솔루션을 개발합니다" },
|
||||
step4: { title: "테스트 및 배포", description: "철저한 테스트를 통해 품질을 보장하고 안정적인 배포를 진행합니다" }
|
||||
},
|
||||
why_choose: {
|
||||
title: "왜 SmartSolTech를 선택해야 할까요?",
|
||||
modern_tech: { title: "최신 기술 활용", description: "항상 최신 기술 트렌드를 파악하고, 검증된 기술 스택을 활용하여 미래 지향적인 솔루션을 제공합니다." },
|
||||
expert_team: { title: "전문가 팀", description: "각 분야의 전문가들로 구성된 팀이 협력하여 최고 품질의 결과물을 보장합니다." },
|
||||
fast_response: { title: "빠른 대응", description: "신속한 의사소통과 빠른 피드백을 통해 프로젝트를 효율적으로 진행합니다." },
|
||||
continuous_support: { title: "지속적인 지원", description: "프로젝트 완료 후에도 지속적인 유지보수와 기술 지원을 제공합니다." },
|
||||
quality_guarantee: { title: "품질 보장", subtitle: "최고 품질의 결과물을 약속드립니다" }
|
||||
},
|
||||
cta: {
|
||||
title: "프로젝트를 시작할 준비가 되셨나요?",
|
||||
subtitle: "지금 바로 무료 상담을 받아보세요",
|
||||
calculate_cost: "비용 계산하기",
|
||||
view_portfolio: "포트폴리오 보기"
|
||||
}
|
||||
},
|
||||
portfolio: {
|
||||
title: { recent: "최근", projects: "프로젝트" },
|
||||
subtitle: "웹, 모바일, 브랜딩 분야의 선별된 작업들",
|
||||
view_all: "전체 포트폴리오 보기",
|
||||
},
|
||||
calculator: {
|
||||
cta: { title: "프로젝트 비용 계산기", subtitle: "몇 가지 질문에 답하여 빠른 견적을 받아보세요", button: "계산기 열기" },
|
||||
},
|
||||
contact: {
|
||||
cta: { ready: "시작할", start: "준비가", question: " 되셨나요?", subtitle: "프로젝트에 대해 알려주세요 - 하루 안에 답변드리겠습니다" },
|
||||
phone: { title: "전화", number: "+82 10-1234-5678" },
|
||||
email: { title: "이메일", address: "hello@smartsoltech.kr" },
|
||||
telegram: { title: "텔레그램", subtitle: "@smartsoltech" },
|
||||
form: {
|
||||
title: "빠른 연락",
|
||||
name: "성함",
|
||||
email: "이메일",
|
||||
phone: "전화번호 (선택사항)",
|
||||
service: {
|
||||
select: "어떤 서비스에 관심이 있으신가요?",
|
||||
web: "웹 개발",
|
||||
mobile: "모바일 앱",
|
||||
design: "UI/UX 디자인",
|
||||
branding: "브랜딩",
|
||||
consulting: "컨설팅",
|
||||
other: "기타",
|
||||
},
|
||||
message: "프로젝트에 대해 알려주세요",
|
||||
submit: "메시지 보내기",
|
||||
},
|
||||
},
|
||||
common: { view_details: "자세히 보기" },
|
||||
theme: { toggle: "테마 변경" }
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ icon: <Code2 className="w-10 h-10" />, title: t.services.web.title, description: t.services.web.description, price: t.services.web.price, delay: 0 },
|
||||
{ icon: <Smartphone className="w-10 h-10" />, title: t.services.mobile.title, description: t.services.mobile.description, price: t.services.mobile.price, delay: 100 },
|
||||
{ icon: <Palette className="w-10 h-10" />, title: t.services.design.title, description: t.services.design.description, price: t.services.design.price, delay: 200 },
|
||||
{ icon: <LineChart className="w-10 h-10" />, title: t.services.marketing.title, description: t.services.marketing.description, price: t.services.marketing.price, delay: 300 },
|
||||
];
|
||||
|
||||
const demoPortfolio = [
|
||||
{
|
||||
_id: "p1",
|
||||
title: "Fintech Dashboard",
|
||||
category: "Web App",
|
||||
images: [{ url: "https://picsum.photos/seed/fin/800/450", isPrimary: true }],
|
||||
technologies: ["React", "Tailwind", "Node"],
|
||||
description: "Realtime analytics with role‑based access.",
|
||||
shortDescription: "Realtime analytics with role‑based access.",
|
||||
viewCount: 423,
|
||||
},
|
||||
{
|
||||
_id: "p2",
|
||||
title: "Wellness Tracker",
|
||||
category: "Mobile",
|
||||
images: [{ url: "https://picsum.photos/seed/well/800/450", isPrimary: true }],
|
||||
technologies: ["Kotlin", "Compose"],
|
||||
description: "Personal health metrics and reminders.",
|
||||
shortDescription: "Personal health metrics and reminders.",
|
||||
viewCount: 1189,
|
||||
},
|
||||
{
|
||||
_id: "p3",
|
||||
title: "Brand Revamp",
|
||||
category: "Branding",
|
||||
images: [{ url: "https://picsum.photos/seed/brand/800/450", isPrimary: true }],
|
||||
technologies: ["Figma", "Design System"],
|
||||
description: "Identity, components, and marketing site.",
|
||||
shortDescription: "Identity, components, and marketing site.",
|
||||
viewCount: 762,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LandingDemo() {
|
||||
useEffect(() => {
|
||||
AOS.init({ duration: 800, easing: "ease-in-out", once: true });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Global styles for blob animation */}
|
||||
<style jsx global>{`
|
||||
@keyframes blob { 0% { transform: translate(0px,0px) scale(1); } 33% { transform: translate(20px,-30px) scale(1.1);} 66% { transform: translate(-10px,20px) scale(0.9);} 100% { transform: translate(0px,0px) scale(1);} }
|
||||
.animate-blob { animation: blob 12s infinite; }
|
||||
.animation-delay-2000 { animation-delay: 2s; }
|
||||
.animation-delay-4000 { animation-delay: 4s; }
|
||||
.glass-effect { backdrop-filter: blur(6px); }
|
||||
.hero-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(1200px 600px at 10% -10%, rgba(99,102,241,.35), transparent 60%), radial-gradient(1000px 500px at 110% 10%, rgba(168,85,247,.35), transparent 60%); pointer-events:none; }
|
||||
.cta-section { background: radial-gradient(1200px 600px at 10% 10%, rgba(59,130,246,.25), transparent 60%), linear-gradient(90deg, #3730a3, #7c3aed); }
|
||||
.form-input { outline: none; }
|
||||
`}</style>
|
||||
|
||||
{/* Hero */}
|
||||
<section className="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900" id="services">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.title.our} <span className="text-blue-600 dark:text-blue-400">{t.services.title.services}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.services.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{services.map((s, i) => (
|
||||
<div key={i} className="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={s.delay}>
|
||||
<div className="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">{s.icon}</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-3">{s.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{s.description}</p>
|
||||
<div className="text-blue-600 dark:text-blue-400 font-semibold">{s.price}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#services" className="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
{t.services.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Portfolio */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800" id="portfolio">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.portfolio.title.recent} <span className="text-purple-600 dark:text-purple-400">{t.portfolio.title.projects}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.portfolio.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{demoPortfolio.map((project, index) => (
|
||||
<div key={project._id} className="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={index * 100}>
|
||||
<div className="relative overflow-hidden">
|
||||
<img src={project.images?.[0]?.url} alt={project.title} className="w-full h-48 object-cover" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies?.slice(0, 3).map((tech) => (
|
||||
<span key={tech} className="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium">{project.category}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm flex items-center"><Eye className="w-4 h-4 mr-1" />{project.viewCount ?? 0}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">{project.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{project.shortDescription ?? project.description}</p>
|
||||
<a href="#" className="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
{t.common.view_details}
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#portfolio" className="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
{t.portfolio.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Calculator CTA */}
|
||||
<section className="py-20 cta-section">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-6">{t.calculator.cta.title}</h2>
|
||||
<p className="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">{t.calculator.cta.subtitle}</p>
|
||||
<a href="#calculator" className="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<Calculator className="mr-3" />
|
||||
{t.calculator.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900" id="contact">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.contact.cta.ready} <span className="text-blue-600 dark:text-blue-400">{t.contact.cta.start}</span>
|
||||
{t.contact.cta.question}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">{t.contact.cta.subtitle}</p>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 5a2 2 0 012-2h3.28a2 2 0 011.94 1.515l.72 2.885a2 2 0 01-.52 1.94L9.12 11.88a16.001 16.001 0 006.999 6.999l1.54-1.28a2 2 0 011.94-.52l2.885.72A2 2 0 0121 20.72V24a2 2 0 01-2 2h-1C9.163 26 2 18.837 2 10V9a2 2 0 011-1.732V5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.phone.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.phone.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 12H8m8 4H8m8-8H8M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.email.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.email.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-green-600 dark:text-green-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 11c1.657 0 3-1.343 3-3S13.657 5 12 5 9 6.343 9 8s1.343 3 3 3zm-7 9a7 7 0 1114 0H5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.telegram.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.telegram.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-aos="fade-left">
|
||||
<div className="p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">{t.contact.form.title}</h3>
|
||||
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||||
<input type="text" placeholder={t.contact.form.name} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="email" placeholder={t.contact.form.email} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="tel" placeholder={t.contact.form.phone} className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<select className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value="">{t.contact.form.service.select}</option>
|
||||
<option value="web">{t.contact.form.service.web}</option>
|
||||
<option value="mobile">{t.contact.form.service.mobile}</option>
|
||||
<option value="design">{t.contact.form.service.design}</option>
|
||||
<option value="branding">{t.contact.form.service.branding}</option>
|
||||
<option value="consulting">{t.contact.form.service.consulting}</option>
|
||||
<option value="other">{t.contact.form.service.other}</option>
|
||||
</select>
|
||||
<textarea rows={4} placeholder={t.contact.form.message} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
<button type="submit" className="w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
{t.contact.form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
517
.history/views/LandingDemo_20251026210038.tsx
Normal file
517
.history/views/LandingDemo_20251026210038.tsx
Normal file
@@ -0,0 +1,517 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
ArrowRight, Calculator, Code2, Smartphone, Palette, LineChart, Eye, Menu, X,
|
||||
Sun, Moon, ChevronDown, Phone, Mail, MessageCircle, Rocket, Users, Clock,
|
||||
Headphones, Award
|
||||
} from "lucide-react";
|
||||
import AOS from "aos";
|
||||
import "aos/dist/aos.css";
|
||||
|
||||
// Korean i18n strings to replace <%- __('...') %>
|
||||
const t = {
|
||||
navigation: {
|
||||
home: "홈",
|
||||
about: "회사소개",
|
||||
services: "서비스",
|
||||
portfolio: "포트폴리오",
|
||||
contact: "연락처",
|
||||
calculator: "비용계산기"
|
||||
},
|
||||
language: {
|
||||
korean: "한국어",
|
||||
english: "English",
|
||||
russian: "Русский",
|
||||
kazakh: "Қазақша"
|
||||
},
|
||||
hero: {
|
||||
title: { smart: "스마트", solutions: "솔루션" },
|
||||
subtitle: "혁신적인 기술로 비즈니스를 성장시키세요",
|
||||
description: "비즈니스의 디지털 전환을 이끄는 혁신적인 웹개발, 모바일 앱, UI/UX 디자인",
|
||||
cta: { start: "시작하기", portfolio: "포트폴리오 보기" },
|
||||
},
|
||||
services: {
|
||||
title: { our: "우리의", services: "서비스" },
|
||||
subtitle: "아이디어를 현실로 만드는 전문 개발 서비스",
|
||||
description: "최첨단 기술과 창의적 아이디어로 완성하는 디지털 솔루션",
|
||||
view_all: "모든 서비스 보기",
|
||||
web: { title: "웹 개발", description: "반응형 웹사이트 및 웹 애플리케이션 개발", price: "500,000원부터" },
|
||||
mobile: { title: "모바일 앱", description: "iOS 및 Android 네이티브 앱 개발", price: "1,000,000원부터" },
|
||||
design: { title: "UI/UX 디자인", description: "사용자 중심의 인터페이스 및 경험 디자인", price: "300,000원부터" },
|
||||
marketing: { title: "디지털 마케팅", description: "SEO, 소셜미디어 마케팅, 광고 관리", price: "200,000원부터" },
|
||||
hero: {
|
||||
title: "우리의",
|
||||
title_highlight: "서비스",
|
||||
subtitle: "혁신적인 기술로 비즈니스 성장 지원"
|
||||
},
|
||||
cards: {
|
||||
starting_price: "시작 가격",
|
||||
consultation: "상담",
|
||||
calculate_cost: "비용 계산",
|
||||
popular: "인기"
|
||||
},
|
||||
process: {
|
||||
title: "프로젝트 수행 과정",
|
||||
subtitle: "체계적이고 전문적인 프로세스로 프로젝트를 진행합니다",
|
||||
step1: { title: "상담 및 기획", description: "고객의 요구사항을 정확히 파악하고 최적의 솔루션을 기획합니다" },
|
||||
step2: { title: "디자인 및 설계", description: "사용자 중심의 직관적인 디자인과 견고한 시스템 아키텍처를 설계합니다" },
|
||||
step3: { title: "개발 및 구현", description: "최신 기술과 모범 사례를 활용하여 효율적이고 확장 가능한 솔루션을 개발합니다" },
|
||||
step4: { title: "테스트 및 배포", description: "철저한 테스트를 통해 품질을 보장하고 안정적인 배포를 진행합니다" }
|
||||
},
|
||||
why_choose: {
|
||||
title: "왜 SmartSolTech를 선택해야 할까요?",
|
||||
modern_tech: { title: "최신 기술 활용", description: "항상 최신 기술 트렌드를 파악하고, 검증된 기술 스택을 활용하여 미래 지향적인 솔루션을 제공합니다." },
|
||||
expert_team: { title: "전문가 팀", description: "각 분야의 전문가들로 구성된 팀이 협력하여 최고 품질의 결과물을 보장합니다." },
|
||||
fast_response: { title: "빠른 대응", description: "신속한 의사소통과 빠른 피드백을 통해 프로젝트를 효율적으로 진행합니다." },
|
||||
continuous_support: { title: "지속적인 지원", description: "프로젝트 완료 후에도 지속적인 유지보수와 기술 지원을 제공합니다." },
|
||||
quality_guarantee: { title: "품질 보장", subtitle: "최고 품질의 결과물을 약속드립니다" }
|
||||
},
|
||||
cta: {
|
||||
title: "프로젝트를 시작할 준비가 되셨나요?",
|
||||
subtitle: "지금 바로 무료 상담을 받아보세요",
|
||||
calculate_cost: "비용 계산하기",
|
||||
view_portfolio: "포트폴리오 보기"
|
||||
}
|
||||
},
|
||||
portfolio: {
|
||||
title: { recent: "최근", projects: "프로젝트" },
|
||||
subtitle: "웹, 모바일, 브랜딩 분야의 선별된 작업들",
|
||||
view_all: "전체 포트폴리오 보기",
|
||||
},
|
||||
calculator: {
|
||||
cta: { title: "프로젝트 비용 계산기", subtitle: "몇 가지 질문에 답하여 빠른 견적을 받아보세요", button: "계산기 열기" },
|
||||
},
|
||||
contact: {
|
||||
cta: { ready: "시작할", start: "준비가", question: " 되셨나요?", subtitle: "프로젝트에 대해 알려주세요 - 하루 안에 답변드리겠습니다" },
|
||||
phone: { title: "전화", number: "+82 10-1234-5678" },
|
||||
email: { title: "이메일", address: "hello@smartsoltech.kr" },
|
||||
telegram: { title: "텔레그램", subtitle: "@smartsoltech" },
|
||||
form: {
|
||||
title: "빠른 연락",
|
||||
name: "성함",
|
||||
email: "이메일",
|
||||
phone: "전화번호 (선택사항)",
|
||||
service: {
|
||||
select: "어떤 서비스에 관심이 있으신가요?",
|
||||
web: "웹 개발",
|
||||
mobile: "모바일 앱",
|
||||
design: "UI/UX 디자인",
|
||||
branding: "브랜딩",
|
||||
consulting: "컨설팅",
|
||||
other: "기타",
|
||||
},
|
||||
message: "프로젝트에 대해 알려주세요",
|
||||
submit: "메시지 보내기",
|
||||
},
|
||||
},
|
||||
common: { view_details: "자세히 보기" },
|
||||
theme: { toggle: "테마 변경" }
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ icon: <Code2 className="w-10 h-10" />, title: t.services.web.title, description: t.services.web.description, price: t.services.web.price, delay: 0, category: "개발" },
|
||||
{ icon: <Smartphone className="w-10 h-10" />, title: t.services.mobile.title, description: t.services.mobile.description, price: t.services.mobile.price, delay: 100, category: "모바일" },
|
||||
{ icon: <Palette className="w-10 h-10" />, title: t.services.design.title, description: t.services.design.description, price: t.services.design.price, delay: 200, category: "디자인" },
|
||||
{ icon: <LineChart className="w-10 h-10" />, title: t.services.marketing.title, description: t.services.marketing.description, price: t.services.marketing.price, delay: 300, category: "마케팅" },
|
||||
];
|
||||
|
||||
const demoPortfolio = [
|
||||
{
|
||||
_id: "p1",
|
||||
title: "핀테크 대시보드",
|
||||
category: "웹앱",
|
||||
images: [{ url: "https://picsum.photos/seed/fin/800/450", isPrimary: true }],
|
||||
technologies: ["React", "Tailwind", "Node"],
|
||||
description: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
shortDescription: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
viewCount: 423,
|
||||
},
|
||||
{
|
||||
_id: "p2",
|
||||
title: "웰니스 트래커",
|
||||
category: "모바일",
|
||||
images: [{ url: "https://picsum.photos/seed/well/800/450", isPrimary: true }],
|
||||
technologies: ["Kotlin", "Compose"],
|
||||
description: "개인 건강 지표 및 알림",
|
||||
shortDescription: "개인 건강 지표 및 알림",
|
||||
viewCount: 1189,
|
||||
},
|
||||
{
|
||||
_id: "p3",
|
||||
title: "브랜드 리뉴얼",
|
||||
category: "브랜딩",
|
||||
images: [{ url: "https://picsum.photos/seed/brand/800/450", isPrimary: true }],
|
||||
technologies: ["Figma", "Design System"],
|
||||
description: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
shortDescription: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
viewCount: 762,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LandingDemo() {
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [currentLanguage, setCurrentLanguage] = useState('ko');
|
||||
|
||||
useEffect(() => {
|
||||
AOS.init({ duration: 800, easing: "ease-in-out", once: true });
|
||||
|
||||
// Check for saved theme preference or default to light mode
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
setDarkMode(true);
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
setDarkMode(!darkMode);
|
||||
if (!darkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('theme', 'light');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setMobileMenuOpen(!mobileMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Global styles for blob animation */}
|
||||
<style jsx global>{`
|
||||
@keyframes blob { 0% { transform: translate(0px,0px) scale(1); } 33% { transform: translate(20px,-30px) scale(1.1);} 66% { transform: translate(-10px,20px) scale(0.9);} 100% { transform: translate(0px,0px) scale(1);} }
|
||||
.animate-blob { animation: blob 12s infinite; }
|
||||
.animation-delay-2000 { animation-delay: 2s; }
|
||||
.animation-delay-4000 { animation-delay: 4s; }
|
||||
.glass-effect { backdrop-filter: blur(6px); }
|
||||
.hero-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(1200px 600px at 10% -10%, rgba(99,102,241,.35), transparent 60%), radial-gradient(1000px 500px at 110% 10%, rgba(168,85,247,.35), transparent 60%); pointer-events:none; }
|
||||
.cta-section { background: radial-gradient(1200px 600px at 10% 10%, rgba(59,130,246,.25), transparent 60%), linear-gradient(90deg, #3730a3, #7c3aed); }
|
||||
.form-input { outline: none; }
|
||||
.theme-toggle-slider { transform: translateX(0); }
|
||||
.dark .theme-toggle-slider { transform: translateX(1.75rem); }
|
||||
.theme-sun-icon { opacity: 1; }
|
||||
.dark .theme-sun-icon { opacity: 0; transform: rotate(180deg); }
|
||||
.theme-moon-icon { opacity: 0; transform: rotate(-180deg); }
|
||||
.dark .theme-moon-icon { opacity: 1; transform: rotate(0deg); }
|
||||
`}</style>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="bg-white dark:bg-gray-900 shadow-lg fixed w-full z-50 top-0 transition-colors duration-300">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16">
|
||||
<div className="flex items-center">
|
||||
{/* Logo */}
|
||||
<a href="/" className="flex-shrink-0 flex items-center">
|
||||
<img className="h-8 w-auto" src="/images/logo.png" alt="SmartSolTech" />
|
||||
<span className="ml-2 text-xl font-bold text-gray-900 dark:text-white">SmartSolTech</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{/* Navigation Links */}
|
||||
<a href="#hero" className="text-blue-600 border-b-2 border-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
|
||||
{/* Language Dropdown */}
|
||||
<div className="relative group">
|
||||
<button className="flex items-center text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors">
|
||||
<span className="mr-2">🇰🇷</span>
|
||||
{t.language.korean}
|
||||
<ChevronDown className="ml-1 w-4 h-4" />
|
||||
</button>
|
||||
<div className="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg border dark:border-gray-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-t-lg">
|
||||
🇰🇷 {t.language.korean}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇺🇸 {t.language.english}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇷🇺 {t.language.russian}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-b-lg">
|
||||
🇰🇿 {t.language.kazakh}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Animated Theme Toggle */}
|
||||
<div className="relative inline-block ml-4" title={t.theme.toggle}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="theme-toggle"
|
||||
className="sr-only"
|
||||
checked={darkMode}
|
||||
onChange={toggleTheme}
|
||||
/>
|
||||
<label htmlFor="theme-toggle" className="flex items-center cursor-pointer">
|
||||
<div className="relative w-14 h-7 bg-gradient-to-r from-blue-200 to-yellow-200 dark:from-gray-700 dark:to-gray-600 rounded-full border-2 border-gray-300 dark:border-gray-500 transition-all duration-300 shadow-sm">
|
||||
<div className="absolute top-0.5 left-1 w-5 h-5 bg-white dark:bg-gray-200 rounded-full shadow-md transform transition-all duration-300 flex items-center justify-center theme-toggle-slider">
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
{/* Sun Icon */}
|
||||
<Sun className="absolute w-3 h-3 text-yellow-500 theme-sun-icon transition-all duration-300 transform" />
|
||||
{/* Moon Icon */}
|
||||
<Moon className="absolute w-3 h-3 text-blue-500 theme-moon-icon transition-all duration-300 transform" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center space-x-2">
|
||||
<button
|
||||
onClick={toggleMobileMenu}
|
||||
className="p-2 text-gray-700 dark:text-gray-300 hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation Menu */}
|
||||
{mobileMenuOpen && (
|
||||
<div className="md:hidden bg-white dark:bg-gray-900 border-t dark:border-gray-700">
|
||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
||||
<a href="#hero" className="bg-blue-50 dark:bg-blue-900 text-blue-600 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900" id="services">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.title.our} <span className="text-blue-600 dark:text-blue-400">{t.services.title.services}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.services.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{services.map((s, i) => (
|
||||
<div key={i} className="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={s.delay}>
|
||||
<div className="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">{s.icon}</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-3">{s.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{s.description}</p>
|
||||
<div className="text-blue-600 dark:text-blue-400 font-semibold">{s.price}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#services" className="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
{t.services.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Portfolio */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800" id="portfolio">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.portfolio.title.recent} <span className="text-purple-600 dark:text-purple-400">{t.portfolio.title.projects}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.portfolio.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{demoPortfolio.map((project, index) => (
|
||||
<div key={project._id} className="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={index * 100}>
|
||||
<div className="relative overflow-hidden">
|
||||
<img src={project.images?.[0]?.url} alt={project.title} className="w-full h-48 object-cover" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies?.slice(0, 3).map((tech) => (
|
||||
<span key={tech} className="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium">{project.category}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm flex items-center"><Eye className="w-4 h-4 mr-1" />{project.viewCount ?? 0}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">{project.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{project.shortDescription ?? project.description}</p>
|
||||
<a href="#" className="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
{t.common.view_details}
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#portfolio" className="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
{t.portfolio.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Calculator CTA */}
|
||||
<section className="py-20 cta-section">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-6">{t.calculator.cta.title}</h2>
|
||||
<p className="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">{t.calculator.cta.subtitle}</p>
|
||||
<a href="#calculator" className="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<Calculator className="mr-3" />
|
||||
{t.calculator.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900" id="contact">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.contact.cta.ready} <span className="text-blue-600 dark:text-blue-400">{t.contact.cta.start}</span>
|
||||
{t.contact.cta.question}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">{t.contact.cta.subtitle}</p>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 5a2 2 0 012-2h3.28a2 2 0 011.94 1.515l.72 2.885a2 2 0 01-.52 1.94L9.12 11.88a16.001 16.001 0 006.999 6.999l1.54-1.28a2 2 0 011.94-.52l2.885.72A2 2 0 0121 20.72V24a2 2 0 01-2 2h-1C9.163 26 2 18.837 2 10V9a2 2 0 011-1.732V5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.phone.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.phone.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 12H8m8 4H8m8-8H8M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.email.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.email.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-green-600 dark:text-green-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 11c1.657 0 3-1.343 3-3S13.657 5 12 5 9 6.343 9 8s1.343 3 3 3zm-7 9a7 7 0 1114 0H5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.telegram.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.telegram.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-aos="fade-left">
|
||||
<div className="p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">{t.contact.form.title}</h3>
|
||||
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||||
<input type="text" placeholder={t.contact.form.name} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="email" placeholder={t.contact.form.email} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="tel" placeholder={t.contact.form.phone} className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<select className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value="">{t.contact.form.service.select}</option>
|
||||
<option value="web">{t.contact.form.service.web}</option>
|
||||
<option value="mobile">{t.contact.form.service.mobile}</option>
|
||||
<option value="design">{t.contact.form.service.design}</option>
|
||||
<option value="branding">{t.contact.form.service.branding}</option>
|
||||
<option value="consulting">{t.contact.form.service.consulting}</option>
|
||||
<option value="other">{t.contact.form.service.other}</option>
|
||||
</select>
|
||||
<textarea rows={4} placeholder={t.contact.form.message} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
<button type="submit" className="w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
{t.contact.form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
752
.history/views/LandingDemo_20251026210146.tsx
Normal file
752
.history/views/LandingDemo_20251026210146.tsx
Normal file
@@ -0,0 +1,752 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
ArrowRight, Calculator, Code2, Smartphone, Palette, LineChart, Eye, Menu, X,
|
||||
Sun, Moon, ChevronDown, Phone, Mail, MessageCircle, Rocket, Users, Clock,
|
||||
Headphones, Award
|
||||
} from "lucide-react";
|
||||
import AOS from "aos";
|
||||
import "aos/dist/aos.css";
|
||||
|
||||
// Korean i18n strings to replace <%- __('...') %>
|
||||
const t = {
|
||||
navigation: {
|
||||
home: "홈",
|
||||
about: "회사소개",
|
||||
services: "서비스",
|
||||
portfolio: "포트폴리오",
|
||||
contact: "연락처",
|
||||
calculator: "비용계산기"
|
||||
},
|
||||
language: {
|
||||
korean: "한국어",
|
||||
english: "English",
|
||||
russian: "Русский",
|
||||
kazakh: "Қазақша"
|
||||
},
|
||||
hero: {
|
||||
title: { smart: "스마트", solutions: "솔루션" },
|
||||
subtitle: "혁신적인 기술로 비즈니스를 성장시키세요",
|
||||
description: "비즈니스의 디지털 전환을 이끄는 혁신적인 웹개발, 모바일 앱, UI/UX 디자인",
|
||||
cta: { start: "시작하기", portfolio: "포트폴리오 보기" },
|
||||
},
|
||||
services: {
|
||||
title: { our: "우리의", services: "서비스" },
|
||||
subtitle: "아이디어를 현실로 만드는 전문 개발 서비스",
|
||||
description: "최첨단 기술과 창의적 아이디어로 완성하는 디지털 솔루션",
|
||||
view_all: "모든 서비스 보기",
|
||||
web: { title: "웹 개발", description: "반응형 웹사이트 및 웹 애플리케이션 개발", price: "500,000원부터" },
|
||||
mobile: { title: "모바일 앱", description: "iOS 및 Android 네이티브 앱 개발", price: "1,000,000원부터" },
|
||||
design: { title: "UI/UX 디자인", description: "사용자 중심의 인터페이스 및 경험 디자인", price: "300,000원부터" },
|
||||
marketing: { title: "디지털 마케팅", description: "SEO, 소셜미디어 마케팅, 광고 관리", price: "200,000원부터" },
|
||||
hero: {
|
||||
title: "우리의",
|
||||
title_highlight: "서비스",
|
||||
subtitle: "혁신적인 기술로 비즈니스 성장 지원"
|
||||
},
|
||||
cards: {
|
||||
starting_price: "시작 가격",
|
||||
consultation: "상담",
|
||||
calculate_cost: "비용 계산",
|
||||
popular: "인기"
|
||||
},
|
||||
process: {
|
||||
title: "프로젝트 수행 과정",
|
||||
subtitle: "체계적이고 전문적인 프로세스로 프로젝트를 진행합니다",
|
||||
step1: { title: "상담 및 기획", description: "고객의 요구사항을 정확히 파악하고 최적의 솔루션을 기획합니다" },
|
||||
step2: { title: "디자인 및 설계", description: "사용자 중심의 직관적인 디자인과 견고한 시스템 아키텍처를 설계합니다" },
|
||||
step3: { title: "개발 및 구현", description: "최신 기술과 모범 사례를 활용하여 효율적이고 확장 가능한 솔루션을 개발합니다" },
|
||||
step4: { title: "테스트 및 배포", description: "철저한 테스트를 통해 품질을 보장하고 안정적인 배포를 진행합니다" }
|
||||
},
|
||||
why_choose: {
|
||||
title: "왜 SmartSolTech를 선택해야 할까요?",
|
||||
modern_tech: { title: "최신 기술 활용", description: "항상 최신 기술 트렌드를 파악하고, 검증된 기술 스택을 활용하여 미래 지향적인 솔루션을 제공합니다." },
|
||||
expert_team: { title: "전문가 팀", description: "각 분야의 전문가들로 구성된 팀이 협력하여 최고 품질의 결과물을 보장합니다." },
|
||||
fast_response: { title: "빠른 대응", description: "신속한 의사소통과 빠른 피드백을 통해 프로젝트를 효율적으로 진행합니다." },
|
||||
continuous_support: { title: "지속적인 지원", description: "프로젝트 완료 후에도 지속적인 유지보수와 기술 지원을 제공합니다." },
|
||||
quality_guarantee: { title: "품질 보장", subtitle: "최고 품질의 결과물을 약속드립니다" }
|
||||
},
|
||||
cta: {
|
||||
title: "프로젝트를 시작할 준비가 되셨나요?",
|
||||
subtitle: "지금 바로 무료 상담을 받아보세요",
|
||||
calculate_cost: "비용 계산하기",
|
||||
view_portfolio: "포트폴리오 보기"
|
||||
}
|
||||
},
|
||||
portfolio: {
|
||||
title: { recent: "최근", projects: "프로젝트" },
|
||||
subtitle: "웹, 모바일, 브랜딩 분야의 선별된 작업들",
|
||||
view_all: "전체 포트폴리오 보기",
|
||||
},
|
||||
calculator: {
|
||||
cta: { title: "프로젝트 비용 계산기", subtitle: "몇 가지 질문에 답하여 빠른 견적을 받아보세요", button: "계산기 열기" },
|
||||
},
|
||||
contact: {
|
||||
cta: { ready: "시작할", start: "준비가", question: " 되셨나요?", subtitle: "프로젝트에 대해 알려주세요 - 하루 안에 답변드리겠습니다" },
|
||||
phone: { title: "전화", number: "+82 10-1234-5678" },
|
||||
email: { title: "이메일", address: "hello@smartsoltech.kr" },
|
||||
telegram: { title: "텔레그램", subtitle: "@smartsoltech" },
|
||||
form: {
|
||||
title: "빠른 연락",
|
||||
name: "성함",
|
||||
email: "이메일",
|
||||
phone: "전화번호 (선택사항)",
|
||||
service: {
|
||||
select: "어떤 서비스에 관심이 있으신가요?",
|
||||
web: "웹 개발",
|
||||
mobile: "모바일 앱",
|
||||
design: "UI/UX 디자인",
|
||||
branding: "브랜딩",
|
||||
consulting: "컨설팅",
|
||||
other: "기타",
|
||||
},
|
||||
message: "프로젝트에 대해 알려주세요",
|
||||
submit: "메시지 보내기",
|
||||
},
|
||||
},
|
||||
common: { view_details: "자세히 보기" },
|
||||
theme: { toggle: "테마 변경" }
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ icon: <Code2 className="w-10 h-10" />, title: t.services.web.title, description: t.services.web.description, price: t.services.web.price, delay: 0, category: "개발" },
|
||||
{ icon: <Smartphone className="w-10 h-10" />, title: t.services.mobile.title, description: t.services.mobile.description, price: t.services.mobile.price, delay: 100, category: "모바일" },
|
||||
{ icon: <Palette className="w-10 h-10" />, title: t.services.design.title, description: t.services.design.description, price: t.services.design.price, delay: 200, category: "디자인" },
|
||||
{ icon: <LineChart className="w-10 h-10" />, title: t.services.marketing.title, description: t.services.marketing.description, price: t.services.marketing.price, delay: 300, category: "마케팅" },
|
||||
];
|
||||
|
||||
const demoPortfolio = [
|
||||
{
|
||||
_id: "p1",
|
||||
title: "핀테크 대시보드",
|
||||
category: "웹앱",
|
||||
images: [{ url: "https://picsum.photos/seed/fin/800/450", isPrimary: true }],
|
||||
technologies: ["React", "Tailwind", "Node"],
|
||||
description: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
shortDescription: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
viewCount: 423,
|
||||
},
|
||||
{
|
||||
_id: "p2",
|
||||
title: "웰니스 트래커",
|
||||
category: "모바일",
|
||||
images: [{ url: "https://picsum.photos/seed/well/800/450", isPrimary: true }],
|
||||
technologies: ["Kotlin", "Compose"],
|
||||
description: "개인 건강 지표 및 알림",
|
||||
shortDescription: "개인 건강 지표 및 알림",
|
||||
viewCount: 1189,
|
||||
},
|
||||
{
|
||||
_id: "p3",
|
||||
title: "브랜드 리뉴얼",
|
||||
category: "브랜딩",
|
||||
images: [{ url: "https://picsum.photos/seed/brand/800/450", isPrimary: true }],
|
||||
technologies: ["Figma", "Design System"],
|
||||
description: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
shortDescription: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
viewCount: 762,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LandingDemo() {
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [currentLanguage, setCurrentLanguage] = useState('ko');
|
||||
|
||||
useEffect(() => {
|
||||
AOS.init({ duration: 800, easing: "ease-in-out", once: true });
|
||||
|
||||
// Check for saved theme preference or default to light mode
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
setDarkMode(true);
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
setDarkMode(!darkMode);
|
||||
if (!darkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('theme', 'light');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setMobileMenuOpen(!mobileMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Global styles for blob animation */}
|
||||
<style jsx global>{`
|
||||
@keyframes blob { 0% { transform: translate(0px,0px) scale(1); } 33% { transform: translate(20px,-30px) scale(1.1);} 66% { transform: translate(-10px,20px) scale(0.9);} 100% { transform: translate(0px,0px) scale(1);} }
|
||||
.animate-blob { animation: blob 12s infinite; }
|
||||
.animation-delay-2000 { animation-delay: 2s; }
|
||||
.animation-delay-4000 { animation-delay: 4s; }
|
||||
.glass-effect { backdrop-filter: blur(6px); }
|
||||
.hero-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(1200px 600px at 10% -10%, rgba(99,102,241,.35), transparent 60%), radial-gradient(1000px 500px at 110% 10%, rgba(168,85,247,.35), transparent 60%); pointer-events:none; }
|
||||
.cta-section { background: radial-gradient(1200px 600px at 10% 10%, rgba(59,130,246,.25), transparent 60%), linear-gradient(90deg, #3730a3, #7c3aed); }
|
||||
.form-input { outline: none; }
|
||||
.theme-toggle-slider { transform: translateX(0); }
|
||||
.dark .theme-toggle-slider { transform: translateX(1.75rem); }
|
||||
.theme-sun-icon { opacity: 1; }
|
||||
.dark .theme-sun-icon { opacity: 0; transform: rotate(180deg); }
|
||||
.theme-moon-icon { opacity: 0; transform: rotate(-180deg); }
|
||||
.dark .theme-moon-icon { opacity: 1; transform: rotate(0deg); }
|
||||
`}</style>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="bg-white dark:bg-gray-900 shadow-lg fixed w-full z-50 top-0 transition-colors duration-300">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16">
|
||||
<div className="flex items-center">
|
||||
{/* Logo */}
|
||||
<a href="/" className="flex-shrink-0 flex items-center">
|
||||
<img className="h-8 w-auto" src="/images/logo.png" alt="SmartSolTech" />
|
||||
<span className="ml-2 text-xl font-bold text-gray-900 dark:text-white">SmartSolTech</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{/* Navigation Links */}
|
||||
<a href="#hero" className="text-blue-600 border-b-2 border-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
|
||||
{/* Language Dropdown */}
|
||||
<div className="relative group">
|
||||
<button className="flex items-center text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors">
|
||||
<span className="mr-2">🇰🇷</span>
|
||||
{t.language.korean}
|
||||
<ChevronDown className="ml-1 w-4 h-4" />
|
||||
</button>
|
||||
<div className="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg border dark:border-gray-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-t-lg">
|
||||
🇰🇷 {t.language.korean}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇺🇸 {t.language.english}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇷🇺 {t.language.russian}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-b-lg">
|
||||
🇰🇿 {t.language.kazakh}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Animated Theme Toggle */}
|
||||
<div className="relative inline-block ml-4" title={t.theme.toggle}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="theme-toggle"
|
||||
className="sr-only"
|
||||
checked={darkMode}
|
||||
onChange={toggleTheme}
|
||||
/>
|
||||
<label htmlFor="theme-toggle" className="flex items-center cursor-pointer">
|
||||
<div className="relative w-14 h-7 bg-gradient-to-r from-blue-200 to-yellow-200 dark:from-gray-700 dark:to-gray-600 rounded-full border-2 border-gray-300 dark:border-gray-500 transition-all duration-300 shadow-sm">
|
||||
<div className="absolute top-0.5 left-1 w-5 h-5 bg-white dark:bg-gray-200 rounded-full shadow-md transform transition-all duration-300 flex items-center justify-center theme-toggle-slider">
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
{/* Sun Icon */}
|
||||
<Sun className="absolute w-3 h-3 text-yellow-500 theme-sun-icon transition-all duration-300 transform" />
|
||||
{/* Moon Icon */}
|
||||
<Moon className="absolute w-3 h-3 text-blue-500 theme-moon-icon transition-all duration-300 transform" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center space-x-2">
|
||||
<button
|
||||
onClick={toggleMobileMenu}
|
||||
className="p-2 text-gray-700 dark:text-gray-300 hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation Menu */}
|
||||
{mobileMenuOpen && (
|
||||
<div className="md:hidden bg-white dark:bg-gray-900 border-t dark:border-gray-700">
|
||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
||||
<a href="#hero" className="bg-blue-50 dark:bg-blue-900 text-blue-600 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Hero */}
|
||||
<section id="hero" className="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section id="services" className="py-20 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.hero.title} <span className="text-yellow-300">{t.services.hero.title_highlight}</span>
|
||||
</h2>
|
||||
<p className="text-xl md:text-2xl mb-8 text-gray-700 dark:text-gray-300">
|
||||
{t.services.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Services Grid */}
|
||||
<div className="space-y-12">
|
||||
{services.map((service, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={index * 150}
|
||||
>
|
||||
{/* Background with Gradient */}
|
||||
<div className={`relative h-64 overflow-hidden ${
|
||||
index % 4 === 0 ? 'bg-gradient-to-r from-blue-600 to-purple-600' :
|
||||
index % 4 === 1 ? 'bg-gradient-to-r from-green-500 to-teal-600' :
|
||||
index % 4 === 2 ? 'bg-gradient-to-r from-purple-600 to-pink-600' :
|
||||
'bg-gradient-to-r from-orange-500 to-red-600'
|
||||
}`}>
|
||||
|
||||
{/* Service Image/Icon Area */}
|
||||
<div className="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div className="relative z-10 text-white">
|
||||
{service.icon}
|
||||
{/* Decorative elements */}
|
||||
<div className="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div className="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style={{animationDelay: '1s'}}></div>
|
||||
</div>
|
||||
|
||||
{/* Gradient fade to center */}
|
||||
<div className="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
{/* Service Content Area */}
|
||||
<div className="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div className="text-right w-full text-white">
|
||||
|
||||
{/* Service Category Badge */}
|
||||
<div className="inline-block mb-4">
|
||||
<span className="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
{service.category}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Service Title */}
|
||||
<h3 className="text-3xl font-bold mb-4 leading-tight">
|
||||
{service.title}
|
||||
</h3>
|
||||
|
||||
{/* Service Description */}
|
||||
<p className="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
{service.description}
|
||||
</p>
|
||||
|
||||
{/* Pricing */}
|
||||
<div className="mb-6">
|
||||
<div className="text-white text-opacity-75 text-sm mb-1">{t.services.cards.starting_price}</div>
|
||||
<div className="text-3xl font-bold text-white">
|
||||
{service.price}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col gap-3 items-end">
|
||||
<a href="#calculator"
|
||||
className="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.services.cards.calculate_cost}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Process Section */}
|
||||
<div className="mt-32">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.process.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-700 dark:text-gray-300 text-center mb-12 max-w-3xl mx-auto">
|
||||
{t.services.process.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{/* Step 1 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div className="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step1.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step1.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div className="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step2.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step2.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div className="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step3.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step3.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 4 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div className="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step4.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step4.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Why Choose Us Section */}
|
||||
<div className="mt-32">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
{/* Content */}
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.services.why_choose.title}
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Feature 1 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Rocket className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.modern_tech.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.modern_tech.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 2 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Users className="w-6 h-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.expert_team.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.expert_team.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 3 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Clock className="w-6 h-6 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.fast_response.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.fast_response.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 4 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-orange-100 dark:bg-orange-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Headphones className="w-6 h-6 text-orange-600 dark:text-orange-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.continuous_support.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.continuous_support.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image/Visual */}
|
||||
<div className="relative" data-aos="fade-left">
|
||||
<div className="bg-gradient-to-br from-blue-100 to-purple-100 dark:from-blue-900 dark:to-purple-900 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<Award className="w-24 h-24 text-blue-600 dark:text-blue-400 mx-auto mb-4" />
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">{t.services.why_choose.quality_guarantee.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.quality_guarantee.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Portfolio */}
|
||||
<section className="py-20 bg-gray-50 dark:bg-gray-800" id="portfolio">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.portfolio.title.recent} <span className="text-purple-600 dark:text-purple-400">{t.portfolio.title.projects}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.portfolio.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{demoPortfolio.map((project, index) => (
|
||||
<div key={project._id} className="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={index * 100}>
|
||||
<div className="relative overflow-hidden">
|
||||
<img src={project.images?.[0]?.url} alt={project.title} className="w-full h-48 object-cover" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies?.slice(0, 3).map((tech) => (
|
||||
<span key={tech} className="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium">{project.category}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm flex items-center"><Eye className="w-4 h-4 mr-1" />{project.viewCount ?? 0}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">{project.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{project.shortDescription ?? project.description}</p>
|
||||
<a href="#" className="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
{t.common.view_details}
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#portfolio" className="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
{t.portfolio.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Calculator CTA */}
|
||||
<section className="py-20 cta-section">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-6">{t.calculator.cta.title}</h2>
|
||||
<p className="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">{t.calculator.cta.subtitle}</p>
|
||||
<a href="#calculator" className="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<Calculator className="mr-3" />
|
||||
{t.calculator.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact */}
|
||||
<section className="py-20 bg-white dark:bg-gray-900" id="contact">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.contact.cta.ready} <span className="text-blue-600 dark:text-blue-400">{t.contact.cta.start}</span>
|
||||
{t.contact.cta.question}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">{t.contact.cta.subtitle}</p>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 5a2 2 0 012-2h3.28a2 2 0 011.94 1.515l.72 2.885a2 2 0 01-.52 1.94L9.12 11.88a16.001 16.001 0 006.999 6.999l1.54-1.28a2 2 0 011.94-.52l2.885.72A2 2 0 0121 20.72V24a2 2 0 01-2 2h-1C9.163 26 2 18.837 2 10V9a2 2 0 011-1.732V5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.phone.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.phone.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 12H8m8 4H8m8-8H8M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.email.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.email.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 text-green-600 dark:text-green-400" fill="none" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 11c1.657 0 3-1.343 3-3S13.657 5 12 5 9 6.343 9 8s1.343 3 3 3zm-7 9a7 7 0 1114 0H5z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.telegram.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.telegram.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-aos="fade-left">
|
||||
<div className="p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">{t.contact.form.title}</h3>
|
||||
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||||
<input type="text" placeholder={t.contact.form.name} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="email" placeholder={t.contact.form.email} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<input type="tel" placeholder={t.contact.form.phone} className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" />
|
||||
<select className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value="">{t.contact.form.service.select}</option>
|
||||
<option value="web">{t.contact.form.service.web}</option>
|
||||
<option value="mobile">{t.contact.form.service.mobile}</option>
|
||||
<option value="design">{t.contact.form.service.design}</option>
|
||||
<option value="branding">{t.contact.form.service.branding}</option>
|
||||
<option value="consulting">{t.contact.form.service.consulting}</option>
|
||||
<option value="other">{t.contact.form.service.other}</option>
|
||||
</select>
|
||||
<textarea rows={4} placeholder={t.contact.form.message} required className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
<button type="submit" className="w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
{t.contact.form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
797
.history/views/LandingDemo_20251026210257.tsx
Normal file
797
.history/views/LandingDemo_20251026210257.tsx
Normal file
@@ -0,0 +1,797 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
ArrowRight, Calculator, Code2, Smartphone, Palette, LineChart, Eye, Menu, X,
|
||||
Sun, Moon, ChevronDown, Phone, Mail, MessageCircle, Rocket, Users, Clock,
|
||||
Headphones, Award
|
||||
} from "lucide-react";
|
||||
import AOS from "aos";
|
||||
import "aos/dist/aos.css";
|
||||
|
||||
// Korean i18n strings to replace <%- __('...') %>
|
||||
const t = {
|
||||
navigation: {
|
||||
home: "홈",
|
||||
about: "회사소개",
|
||||
services: "서비스",
|
||||
portfolio: "포트폴리오",
|
||||
contact: "연락처",
|
||||
calculator: "비용계산기"
|
||||
},
|
||||
language: {
|
||||
korean: "한국어",
|
||||
english: "English",
|
||||
russian: "Русский",
|
||||
kazakh: "Қазақша"
|
||||
},
|
||||
hero: {
|
||||
title: { smart: "스마트", solutions: "솔루션" },
|
||||
subtitle: "혁신적인 기술로 비즈니스를 성장시키세요",
|
||||
description: "비즈니스의 디지털 전환을 이끄는 혁신적인 웹개발, 모바일 앱, UI/UX 디자인",
|
||||
cta: { start: "시작하기", portfolio: "포트폴리오 보기" },
|
||||
},
|
||||
services: {
|
||||
title: { our: "우리의", services: "서비스" },
|
||||
subtitle: "아이디어를 현실로 만드는 전문 개발 서비스",
|
||||
description: "최첨단 기술과 창의적 아이디어로 완성하는 디지털 솔루션",
|
||||
view_all: "모든 서비스 보기",
|
||||
web: { title: "웹 개발", description: "반응형 웹사이트 및 웹 애플리케이션 개발", price: "500,000원부터" },
|
||||
mobile: { title: "모바일 앱", description: "iOS 및 Android 네이티브 앱 개발", price: "1,000,000원부터" },
|
||||
design: { title: "UI/UX 디자인", description: "사용자 중심의 인터페이스 및 경험 디자인", price: "300,000원부터" },
|
||||
marketing: { title: "디지털 마케팅", description: "SEO, 소셜미디어 마케팅, 광고 관리", price: "200,000원부터" },
|
||||
hero: {
|
||||
title: "우리의",
|
||||
title_highlight: "서비스",
|
||||
subtitle: "혁신적인 기술로 비즈니스 성장 지원"
|
||||
},
|
||||
cards: {
|
||||
starting_price: "시작 가격",
|
||||
consultation: "상담",
|
||||
calculate_cost: "비용 계산",
|
||||
popular: "인기"
|
||||
},
|
||||
process: {
|
||||
title: "프로젝트 수행 과정",
|
||||
subtitle: "체계적이고 전문적인 프로세스로 프로젝트를 진행합니다",
|
||||
step1: { title: "상담 및 기획", description: "고객의 요구사항을 정확히 파악하고 최적의 솔루션을 기획합니다" },
|
||||
step2: { title: "디자인 및 설계", description: "사용자 중심의 직관적인 디자인과 견고한 시스템 아키텍처를 설계합니다" },
|
||||
step3: { title: "개발 및 구현", description: "최신 기술과 모범 사례를 활용하여 효율적이고 확장 가능한 솔루션을 개발합니다" },
|
||||
step4: { title: "테스트 및 배포", description: "철저한 테스트를 통해 품질을 보장하고 안정적인 배포를 진행합니다" }
|
||||
},
|
||||
why_choose: {
|
||||
title: "왜 SmartSolTech를 선택해야 할까요?",
|
||||
modern_tech: { title: "최신 기술 활용", description: "항상 최신 기술 트렌드를 파악하고, 검증된 기술 스택을 활용하여 미래 지향적인 솔루션을 제공합니다." },
|
||||
expert_team: { title: "전문가 팀", description: "각 분야의 전문가들로 구성된 팀이 협력하여 최고 품질의 결과물을 보장합니다." },
|
||||
fast_response: { title: "빠른 대응", description: "신속한 의사소통과 빠른 피드백을 통해 프로젝트를 효율적으로 진행합니다." },
|
||||
continuous_support: { title: "지속적인 지원", description: "프로젝트 완료 후에도 지속적인 유지보수와 기술 지원을 제공합니다." },
|
||||
quality_guarantee: { title: "품질 보장", subtitle: "최고 품질의 결과물을 약속드립니다" }
|
||||
},
|
||||
cta: {
|
||||
title: "프로젝트를 시작할 준비가 되셨나요?",
|
||||
subtitle: "지금 바로 무료 상담을 받아보세요",
|
||||
calculate_cost: "비용 계산하기",
|
||||
view_portfolio: "포트폴리오 보기"
|
||||
}
|
||||
},
|
||||
portfolio: {
|
||||
title: { recent: "최근", projects: "프로젝트" },
|
||||
subtitle: "웹, 모바일, 브랜딩 분야의 선별된 작업들",
|
||||
view_all: "전체 포트폴리오 보기",
|
||||
},
|
||||
calculator: {
|
||||
cta: { title: "프로젝트 비용 계산기", subtitle: "몇 가지 질문에 답하여 빠른 견적을 받아보세요", button: "계산기 열기" },
|
||||
},
|
||||
contact: {
|
||||
cta: { ready: "시작할", start: "준비가", question: " 되셨나요?", subtitle: "프로젝트에 대해 알려주세요 - 하루 안에 답변드리겠습니다" },
|
||||
phone: { title: "전화", number: "+82 10-1234-5678" },
|
||||
email: { title: "이메일", address: "hello@smartsoltech.kr" },
|
||||
telegram: { title: "텔레그램", subtitle: "@smartsoltech" },
|
||||
form: {
|
||||
title: "빠른 연락",
|
||||
name: "성함",
|
||||
email: "이메일",
|
||||
phone: "전화번호 (선택사항)",
|
||||
service: {
|
||||
select: "어떤 서비스에 관심이 있으신가요?",
|
||||
web: "웹 개발",
|
||||
mobile: "모바일 앱",
|
||||
design: "UI/UX 디자인",
|
||||
branding: "브랜딩",
|
||||
consulting: "컨설팅",
|
||||
other: "기타",
|
||||
},
|
||||
message: "프로젝트에 대해 알려주세요",
|
||||
submit: "메시지 보내기",
|
||||
},
|
||||
},
|
||||
common: { view_details: "자세히 보기" },
|
||||
theme: { toggle: "테마 변경" }
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ icon: <Code2 className="w-10 h-10" />, title: t.services.web.title, description: t.services.web.description, price: t.services.web.price, delay: 0, category: "개발" },
|
||||
{ icon: <Smartphone className="w-10 h-10" />, title: t.services.mobile.title, description: t.services.mobile.description, price: t.services.mobile.price, delay: 100, category: "모바일" },
|
||||
{ icon: <Palette className="w-10 h-10" />, title: t.services.design.title, description: t.services.design.description, price: t.services.design.price, delay: 200, category: "디자인" },
|
||||
{ icon: <LineChart className="w-10 h-10" />, title: t.services.marketing.title, description: t.services.marketing.description, price: t.services.marketing.price, delay: 300, category: "마케팅" },
|
||||
];
|
||||
|
||||
const demoPortfolio = [
|
||||
{
|
||||
_id: "p1",
|
||||
title: "핀테크 대시보드",
|
||||
category: "웹앱",
|
||||
images: [{ url: "https://picsum.photos/seed/fin/800/450", isPrimary: true }],
|
||||
technologies: ["React", "Tailwind", "Node"],
|
||||
description: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
shortDescription: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
viewCount: 423,
|
||||
},
|
||||
{
|
||||
_id: "p2",
|
||||
title: "웰니스 트래커",
|
||||
category: "모바일",
|
||||
images: [{ url: "https://picsum.photos/seed/well/800/450", isPrimary: true }],
|
||||
technologies: ["Kotlin", "Compose"],
|
||||
description: "개인 건강 지표 및 알림",
|
||||
shortDescription: "개인 건강 지표 및 알림",
|
||||
viewCount: 1189,
|
||||
},
|
||||
{
|
||||
_id: "p3",
|
||||
title: "브랜드 리뉴얼",
|
||||
category: "브랜딩",
|
||||
images: [{ url: "https://picsum.photos/seed/brand/800/450", isPrimary: true }],
|
||||
technologies: ["Figma", "Design System"],
|
||||
description: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
shortDescription: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
viewCount: 762,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LandingDemo() {
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [currentLanguage, setCurrentLanguage] = useState('ko');
|
||||
|
||||
useEffect(() => {
|
||||
AOS.init({ duration: 800, easing: "ease-in-out", once: true });
|
||||
|
||||
// Check for saved theme preference or default to light mode
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
setDarkMode(true);
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
setDarkMode(!darkMode);
|
||||
if (!darkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('theme', 'light');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setMobileMenuOpen(!mobileMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Global styles for blob animation */}
|
||||
<style jsx global>{`
|
||||
@keyframes blob { 0% { transform: translate(0px,0px) scale(1); } 33% { transform: translate(20px,-30px) scale(1.1);} 66% { transform: translate(-10px,20px) scale(0.9);} 100% { transform: translate(0px,0px) scale(1);} }
|
||||
.animate-blob { animation: blob 12s infinite; }
|
||||
.animation-delay-2000 { animation-delay: 2s; }
|
||||
.animation-delay-4000 { animation-delay: 4s; }
|
||||
.glass-effect { backdrop-filter: blur(6px); }
|
||||
.hero-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(1200px 600px at 10% -10%, rgba(99,102,241,.35), transparent 60%), radial-gradient(1000px 500px at 110% 10%, rgba(168,85,247,.35), transparent 60%); pointer-events:none; }
|
||||
.cta-section { background: radial-gradient(1200px 600px at 10% 10%, rgba(59,130,246,.25), transparent 60%), linear-gradient(90deg, #3730a3, #7c3aed); }
|
||||
.form-input { outline: none; }
|
||||
.theme-toggle-slider { transform: translateX(0); }
|
||||
.dark .theme-toggle-slider { transform: translateX(1.75rem); }
|
||||
.theme-sun-icon { opacity: 1; }
|
||||
.dark .theme-sun-icon { opacity: 0; transform: rotate(180deg); }
|
||||
.theme-moon-icon { opacity: 0; transform: rotate(-180deg); }
|
||||
.dark .theme-moon-icon { opacity: 1; transform: rotate(0deg); }
|
||||
`}</style>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="bg-white dark:bg-gray-900 shadow-lg fixed w-full z-50 top-0 transition-colors duration-300">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16">
|
||||
<div className="flex items-center">
|
||||
{/* Logo */}
|
||||
<a href="/" className="flex-shrink-0 flex items-center">
|
||||
<img className="h-8 w-auto" src="/images/logo.png" alt="SmartSolTech" />
|
||||
<span className="ml-2 text-xl font-bold text-gray-900 dark:text-white">SmartSolTech</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{/* Navigation Links */}
|
||||
<a href="#hero" className="text-blue-600 border-b-2 border-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
|
||||
{/* Language Dropdown */}
|
||||
<div className="relative group">
|
||||
<button className="flex items-center text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors">
|
||||
<span className="mr-2">🇰🇷</span>
|
||||
{t.language.korean}
|
||||
<ChevronDown className="ml-1 w-4 h-4" />
|
||||
</button>
|
||||
<div className="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg border dark:border-gray-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-t-lg">
|
||||
🇰🇷 {t.language.korean}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇺🇸 {t.language.english}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇷🇺 {t.language.russian}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-b-lg">
|
||||
🇰🇿 {t.language.kazakh}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Animated Theme Toggle */}
|
||||
<div className="relative inline-block ml-4" title={t.theme.toggle}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="theme-toggle"
|
||||
className="sr-only"
|
||||
checked={darkMode}
|
||||
onChange={toggleTheme}
|
||||
/>
|
||||
<label htmlFor="theme-toggle" className="flex items-center cursor-pointer">
|
||||
<div className="relative w-14 h-7 bg-gradient-to-r from-blue-200 to-yellow-200 dark:from-gray-700 dark:to-gray-600 rounded-full border-2 border-gray-300 dark:border-gray-500 transition-all duration-300 shadow-sm">
|
||||
<div className="absolute top-0.5 left-1 w-5 h-5 bg-white dark:bg-gray-200 rounded-full shadow-md transform transition-all duration-300 flex items-center justify-center theme-toggle-slider">
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
{/* Sun Icon */}
|
||||
<Sun className="absolute w-3 h-3 text-yellow-500 theme-sun-icon transition-all duration-300 transform" />
|
||||
{/* Moon Icon */}
|
||||
<Moon className="absolute w-3 h-3 text-blue-500 theme-moon-icon transition-all duration-300 transform" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center space-x-2">
|
||||
<button
|
||||
onClick={toggleMobileMenu}
|
||||
className="p-2 text-gray-700 dark:text-gray-300 hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation Menu */}
|
||||
{mobileMenuOpen && (
|
||||
<div className="md:hidden bg-white dark:bg-gray-900 border-t dark:border-gray-700">
|
||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
||||
<a href="#hero" className="bg-blue-50 dark:bg-blue-900 text-blue-600 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Hero */}
|
||||
<section id="hero" className="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section id="services" className="py-20 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.hero.title} <span className="text-yellow-300">{t.services.hero.title_highlight}</span>
|
||||
</h2>
|
||||
<p className="text-xl md:text-2xl mb-8 text-gray-700 dark:text-gray-300">
|
||||
{t.services.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Services Grid */}
|
||||
<div className="space-y-12">
|
||||
{services.map((service, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={index * 150}
|
||||
>
|
||||
{/* Background with Gradient */}
|
||||
<div className={`relative h-64 overflow-hidden ${
|
||||
index % 4 === 0 ? 'bg-gradient-to-r from-blue-600 to-purple-600' :
|
||||
index % 4 === 1 ? 'bg-gradient-to-r from-green-500 to-teal-600' :
|
||||
index % 4 === 2 ? 'bg-gradient-to-r from-purple-600 to-pink-600' :
|
||||
'bg-gradient-to-r from-orange-500 to-red-600'
|
||||
}`}>
|
||||
|
||||
{/* Service Image/Icon Area */}
|
||||
<div className="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div className="relative z-10 text-white">
|
||||
{service.icon}
|
||||
{/* Decorative elements */}
|
||||
<div className="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div className="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style={{animationDelay: '1s'}}></div>
|
||||
</div>
|
||||
|
||||
{/* Gradient fade to center */}
|
||||
<div className="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
{/* Service Content Area */}
|
||||
<div className="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div className="text-right w-full text-white">
|
||||
|
||||
{/* Service Category Badge */}
|
||||
<div className="inline-block mb-4">
|
||||
<span className="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
{service.category}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Service Title */}
|
||||
<h3 className="text-3xl font-bold mb-4 leading-tight">
|
||||
{service.title}
|
||||
</h3>
|
||||
|
||||
{/* Service Description */}
|
||||
<p className="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
{service.description}
|
||||
</p>
|
||||
|
||||
{/* Pricing */}
|
||||
<div className="mb-6">
|
||||
<div className="text-white text-opacity-75 text-sm mb-1">{t.services.cards.starting_price}</div>
|
||||
<div className="text-3xl font-bold text-white">
|
||||
{service.price}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col gap-3 items-end">
|
||||
<a href="#calculator"
|
||||
className="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.services.cards.calculate_cost}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Process Section */}
|
||||
<div className="mt-32">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.process.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-700 dark:text-gray-300 text-center mb-12 max-w-3xl mx-auto">
|
||||
{t.services.process.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{/* Step 1 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div className="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step1.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step1.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div className="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step2.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step2.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div className="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step3.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step3.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 4 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div className="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step4.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step4.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Why Choose Us Section */}
|
||||
<div className="mt-32">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
{/* Content */}
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.services.why_choose.title}
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Feature 1 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Rocket className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.modern_tech.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.modern_tech.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 2 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Users className="w-6 h-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.expert_team.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.expert_team.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 3 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Clock className="w-6 h-6 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.fast_response.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.fast_response.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 4 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-orange-100 dark:bg-orange-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Headphones className="w-6 h-6 text-orange-600 dark:text-orange-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.continuous_support.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.continuous_support.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image/Visual */}
|
||||
<div className="relative" data-aos="fade-left">
|
||||
<div className="bg-gradient-to-br from-blue-100 to-purple-100 dark:from-blue-900 dark:to-purple-900 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<Award className="w-24 h-24 text-blue-600 dark:text-blue-400 mx-auto mb-4" />
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">{t.services.why_choose.quality_guarantee.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.quality_guarantee.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Portfolio */}
|
||||
<section id="portfolio" className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.portfolio.title.recent} <span className="text-purple-600 dark:text-purple-400">{t.portfolio.title.projects}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.portfolio.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{demoPortfolio.map((project, index) => (
|
||||
<div key={project._id} className="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={index * 100}>
|
||||
<div className="relative overflow-hidden">
|
||||
<img src={project.images?.[0]?.url} alt={project.title} className="w-full h-48 object-cover" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies?.slice(0, 3).map((tech) => (
|
||||
<span key={tech} className="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium">{project.category}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm flex items-center"><Eye className="w-4 h-4 mr-1" />{project.viewCount ?? 0}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">{project.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{project.shortDescription ?? project.description}</p>
|
||||
<a href="#" className="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
{t.common.view_details}
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#portfolio" className="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
{t.portfolio.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Calculator CTA */}
|
||||
<section id="calculator" className="py-20 cta-section">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-6">{t.calculator.cta.title}</h2>
|
||||
<p className="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">{t.calculator.cta.subtitle}</p>
|
||||
<a href="#calculator" className="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<Calculator className="mr-3" />
|
||||
{t.calculator.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services CTA */}
|
||||
<section className="py-20 bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
{t.services.cta.title}
|
||||
</h2>
|
||||
<p className="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.services.cta.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#calculator" className="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
{t.services.cta.calculate_cost}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
{t.services.cta.view_portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact */}
|
||||
<section id="contact" className="py-20 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.contact.cta.ready} <span className="text-blue-600 dark:text-blue-400">{t.contact.cta.start}</span>
|
||||
{t.contact.cta.question}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">{t.contact.cta.subtitle}</p>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<Phone className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.phone.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.phone.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<Mail className="w-6 h-6 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.email.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.email.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<MessageCircle className="w-6 h-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.telegram.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.telegram.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-aos="fade-left">
|
||||
<div className="p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">{t.contact.form.title}</h3>
|
||||
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={t.contact.form.name}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<input
|
||||
type="email"
|
||||
placeholder={t.contact.form.email}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<input
|
||||
type="tel"
|
||||
placeholder={t.contact.form.phone}
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<select
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
title={t.contact.form.service.select}
|
||||
>
|
||||
<option value="">{t.contact.form.service.select}</option>
|
||||
<option value="web">{t.contact.form.service.web}</option>
|
||||
<option value="mobile">{t.contact.form.service.mobile}</option>
|
||||
<option value="design">{t.contact.form.service.design}</option>
|
||||
<option value="branding">{t.contact.form.service.branding}</option>
|
||||
<option value="consulting">{t.contact.form.service.consulting}</option>
|
||||
<option value="other">{t.contact.form.service.other}</option>
|
||||
</select>
|
||||
<textarea
|
||||
rows={4}
|
||||
placeholder={t.contact.form.message}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"
|
||||
></textarea>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105"
|
||||
>
|
||||
{t.contact.form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
797
.history/views/LandingDemo_20251026210326.tsx
Normal file
797
.history/views/LandingDemo_20251026210326.tsx
Normal file
@@ -0,0 +1,797 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
ArrowRight, Calculator, Code2, Smartphone, Palette, LineChart, Eye, Menu, X,
|
||||
Sun, Moon, ChevronDown, Phone, Mail, MessageCircle, Rocket, Users, Clock,
|
||||
Headphones, Award
|
||||
} from "lucide-react";
|
||||
import AOS from "aos";
|
||||
import "aos/dist/aos.css";
|
||||
|
||||
// Korean i18n strings to replace <%- __('...') %>
|
||||
const t = {
|
||||
navigation: {
|
||||
home: "홈",
|
||||
about: "회사소개",
|
||||
services: "서비스",
|
||||
portfolio: "포트폴리오",
|
||||
contact: "연락처",
|
||||
calculator: "비용계산기"
|
||||
},
|
||||
language: {
|
||||
korean: "한국어",
|
||||
english: "English",
|
||||
russian: "Русский",
|
||||
kazakh: "Қазақша"
|
||||
},
|
||||
hero: {
|
||||
title: { smart: "스마트", solutions: "솔루션" },
|
||||
subtitle: "혁신적인 기술로 비즈니스를 성장시키세요",
|
||||
description: "비즈니스의 디지털 전환을 이끄는 혁신적인 웹개발, 모바일 앱, UI/UX 디자인",
|
||||
cta: { start: "시작하기", portfolio: "포트폴리오 보기" },
|
||||
},
|
||||
services: {
|
||||
title: { our: "우리의", services: "서비스" },
|
||||
subtitle: "아이디어를 현실로 만드는 전문 개발 서비스",
|
||||
description: "최첨단 기술과 창의적 아이디어로 완성하는 디지털 솔루션",
|
||||
view_all: "모든 서비스 보기",
|
||||
web: { title: "웹 개발", description: "반응형 웹사이트 및 웹 애플리케이션 개발", price: "500,000원부터" },
|
||||
mobile: { title: "모바일 앱", description: "iOS 및 Android 네이티브 앱 개발", price: "1,000,000원부터" },
|
||||
design: { title: "UI/UX 디자인", description: "사용자 중심의 인터페이스 및 경험 디자인", price: "300,000원부터" },
|
||||
marketing: { title: "디지털 마케팅", description: "SEO, 소셜미디어 마케팅, 광고 관리", price: "200,000원부터" },
|
||||
hero: {
|
||||
title: "우리의",
|
||||
title_highlight: "서비스",
|
||||
subtitle: "혁신적인 기술로 비즈니스 성장 지원"
|
||||
},
|
||||
cards: {
|
||||
starting_price: "시작 가격",
|
||||
consultation: "상담",
|
||||
calculate_cost: "비용 계산",
|
||||
popular: "인기"
|
||||
},
|
||||
process: {
|
||||
title: "프로젝트 수행 과정",
|
||||
subtitle: "체계적이고 전문적인 프로세스로 프로젝트를 진행합니다",
|
||||
step1: { title: "상담 및 기획", description: "고객의 요구사항을 정확히 파악하고 최적의 솔루션을 기획합니다" },
|
||||
step2: { title: "디자인 및 설계", description: "사용자 중심의 직관적인 디자인과 견고한 시스템 아키텍처를 설계합니다" },
|
||||
step3: { title: "개발 및 구현", description: "최신 기술과 모범 사례를 활용하여 효율적이고 확장 가능한 솔루션을 개발합니다" },
|
||||
step4: { title: "테스트 및 배포", description: "철저한 테스트를 통해 품질을 보장하고 안정적인 배포를 진행합니다" }
|
||||
},
|
||||
why_choose: {
|
||||
title: "왜 SmartSolTech를 선택해야 할까요?",
|
||||
modern_tech: { title: "최신 기술 활용", description: "항상 최신 기술 트렌드를 파악하고, 검증된 기술 스택을 활용하여 미래 지향적인 솔루션을 제공합니다." },
|
||||
expert_team: { title: "전문가 팀", description: "각 분야의 전문가들로 구성된 팀이 협력하여 최고 품질의 결과물을 보장합니다." },
|
||||
fast_response: { title: "빠른 대응", description: "신속한 의사소통과 빠른 피드백을 통해 프로젝트를 효율적으로 진행합니다." },
|
||||
continuous_support: { title: "지속적인 지원", description: "프로젝트 완료 후에도 지속적인 유지보수와 기술 지원을 제공합니다." },
|
||||
quality_guarantee: { title: "품질 보장", subtitle: "최고 품질의 결과물을 약속드립니다" }
|
||||
},
|
||||
cta: {
|
||||
title: "프로젝트를 시작할 준비가 되셨나요?",
|
||||
subtitle: "지금 바로 무료 상담을 받아보세요",
|
||||
calculate_cost: "비용 계산하기",
|
||||
view_portfolio: "포트폴리오 보기"
|
||||
}
|
||||
},
|
||||
portfolio: {
|
||||
title: { recent: "최근", projects: "프로젝트" },
|
||||
subtitle: "웹, 모바일, 브랜딩 분야의 선별된 작업들",
|
||||
view_all: "전체 포트폴리오 보기",
|
||||
},
|
||||
calculator: {
|
||||
cta: { title: "프로젝트 비용 계산기", subtitle: "몇 가지 질문에 답하여 빠른 견적을 받아보세요", button: "계산기 열기" },
|
||||
},
|
||||
contact: {
|
||||
cta: { ready: "시작할", start: "준비가", question: " 되셨나요?", subtitle: "프로젝트에 대해 알려주세요 - 하루 안에 답변드리겠습니다" },
|
||||
phone: { title: "전화", number: "+82 10-1234-5678" },
|
||||
email: { title: "이메일", address: "hello@smartsoltech.kr" },
|
||||
telegram: { title: "텔레그램", subtitle: "@smartsoltech" },
|
||||
form: {
|
||||
title: "빠른 연락",
|
||||
name: "성함",
|
||||
email: "이메일",
|
||||
phone: "전화번호 (선택사항)",
|
||||
service: {
|
||||
select: "어떤 서비스에 관심이 있으신가요?",
|
||||
web: "웹 개발",
|
||||
mobile: "모바일 앱",
|
||||
design: "UI/UX 디자인",
|
||||
branding: "브랜딩",
|
||||
consulting: "컨설팅",
|
||||
other: "기타",
|
||||
},
|
||||
message: "프로젝트에 대해 알려주세요",
|
||||
submit: "메시지 보내기",
|
||||
},
|
||||
},
|
||||
common: { view_details: "자세히 보기" },
|
||||
theme: { toggle: "테마 변경" }
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ icon: <Code2 className="w-10 h-10" />, title: t.services.web.title, description: t.services.web.description, price: t.services.web.price, delay: 0, category: "개발" },
|
||||
{ icon: <Smartphone className="w-10 h-10" />, title: t.services.mobile.title, description: t.services.mobile.description, price: t.services.mobile.price, delay: 100, category: "모바일" },
|
||||
{ icon: <Palette className="w-10 h-10" />, title: t.services.design.title, description: t.services.design.description, price: t.services.design.price, delay: 200, category: "디자인" },
|
||||
{ icon: <LineChart className="w-10 h-10" />, title: t.services.marketing.title, description: t.services.marketing.description, price: t.services.marketing.price, delay: 300, category: "마케팅" },
|
||||
];
|
||||
|
||||
const demoPortfolio = [
|
||||
{
|
||||
_id: "p1",
|
||||
title: "핀테크 대시보드",
|
||||
category: "웹앱",
|
||||
images: [{ url: "https://picsum.photos/seed/fin/800/450", isPrimary: true }],
|
||||
technologies: ["React", "Tailwind", "Node"],
|
||||
description: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
shortDescription: "역할 기반 접근 제어를 갖춘 실시간 분석",
|
||||
viewCount: 423,
|
||||
},
|
||||
{
|
||||
_id: "p2",
|
||||
title: "웰니스 트래커",
|
||||
category: "모바일",
|
||||
images: [{ url: "https://picsum.photos/seed/well/800/450", isPrimary: true }],
|
||||
technologies: ["Kotlin", "Compose"],
|
||||
description: "개인 건강 지표 및 알림",
|
||||
shortDescription: "개인 건강 지표 및 알림",
|
||||
viewCount: 1189,
|
||||
},
|
||||
{
|
||||
_id: "p3",
|
||||
title: "브랜드 리뉴얼",
|
||||
category: "브랜딩",
|
||||
images: [{ url: "https://picsum.photos/seed/brand/800/450", isPrimary: true }],
|
||||
technologies: ["Figma", "Design System"],
|
||||
description: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
shortDescription: "아이덴티티, 컴포넌트 및 마케팅 사이트",
|
||||
viewCount: 762,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LandingDemo() {
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [currentLanguage, setCurrentLanguage] = useState('ko');
|
||||
|
||||
useEffect(() => {
|
||||
AOS.init({ duration: 800, easing: "ease-in-out", once: true });
|
||||
|
||||
// Check for saved theme preference or default to light mode
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
setDarkMode(true);
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
setDarkMode(!darkMode);
|
||||
if (!darkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('theme', 'light');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setMobileMenuOpen(!mobileMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Global styles for blob animation */}
|
||||
<style jsx global>{`
|
||||
@keyframes blob { 0% { transform: translate(0px,0px) scale(1); } 33% { transform: translate(20px,-30px) scale(1.1);} 66% { transform: translate(-10px,20px) scale(0.9);} 100% { transform: translate(0px,0px) scale(1);} }
|
||||
.animate-blob { animation: blob 12s infinite; }
|
||||
.animation-delay-2000 { animation-delay: 2s; }
|
||||
.animation-delay-4000 { animation-delay: 4s; }
|
||||
.glass-effect { backdrop-filter: blur(6px); }
|
||||
.hero-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(1200px 600px at 10% -10%, rgba(99,102,241,.35), transparent 60%), radial-gradient(1000px 500px at 110% 10%, rgba(168,85,247,.35), transparent 60%); pointer-events:none; }
|
||||
.cta-section { background: radial-gradient(1200px 600px at 10% 10%, rgba(59,130,246,.25), transparent 60%), linear-gradient(90deg, #3730a3, #7c3aed); }
|
||||
.form-input { outline: none; }
|
||||
.theme-toggle-slider { transform: translateX(0); }
|
||||
.dark .theme-toggle-slider { transform: translateX(1.75rem); }
|
||||
.theme-sun-icon { opacity: 1; }
|
||||
.dark .theme-sun-icon { opacity: 0; transform: rotate(180deg); }
|
||||
.theme-moon-icon { opacity: 0; transform: rotate(-180deg); }
|
||||
.dark .theme-moon-icon { opacity: 1; transform: rotate(0deg); }
|
||||
`}</style>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="bg-white dark:bg-gray-900 shadow-lg fixed w-full z-50 top-0 transition-colors duration-300">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16">
|
||||
<div className="flex items-center">
|
||||
{/* Logo */}
|
||||
<a href="/" className="flex-shrink-0 flex items-center">
|
||||
<img className="h-8 w-auto" src="/images/logo.png" alt="SmartSolTech" />
|
||||
<span className="ml-2 text-xl font-bold text-gray-900 dark:text-white">SmartSolTech</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{/* Navigation Links */}
|
||||
<a href="#hero" className="text-blue-600 border-b-2 border-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors nav-link">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
|
||||
{/* Language Dropdown */}
|
||||
<div className="relative group">
|
||||
<button className="flex items-center text-gray-700 dark:text-gray-300 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors">
|
||||
<span className="mr-2">🇰🇷</span>
|
||||
{t.language.korean}
|
||||
<ChevronDown className="ml-1 w-4 h-4" />
|
||||
</button>
|
||||
<div className="absolute right-0 mt-2 w-40 bg-white dark:bg-gray-800 rounded-lg shadow-lg border dark:border-gray-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-t-lg">
|
||||
🇰🇷 {t.language.korean}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇺🇸 {t.language.english}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
🇷🇺 {t.language.russian}
|
||||
</a>
|
||||
<a href="#" className="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-b-lg">
|
||||
🇰🇿 {t.language.kazakh}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Animated Theme Toggle */}
|
||||
<div className="relative inline-block ml-4" title={t.theme.toggle}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="theme-toggle"
|
||||
className="sr-only"
|
||||
checked={darkMode}
|
||||
onChange={toggleTheme}
|
||||
/>
|
||||
<label htmlFor="theme-toggle" className="flex items-center cursor-pointer">
|
||||
<div className="relative w-14 h-7 bg-gradient-to-r from-blue-200 to-yellow-200 dark:from-gray-700 dark:to-gray-600 rounded-full border-2 border-gray-300 dark:border-gray-500 transition-all duration-300 shadow-sm">
|
||||
<div className="absolute top-0.5 left-1 w-5 h-5 bg-white dark:bg-gray-200 rounded-full shadow-md transform transition-all duration-300 flex items-center justify-center theme-toggle-slider">
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
{/* Sun Icon */}
|
||||
<Sun className="absolute w-3 h-3 text-yellow-500 theme-sun-icon transition-all duration-300 transform" />
|
||||
{/* Moon Icon */}
|
||||
<Moon className="absolute w-3 h-3 text-blue-500 theme-moon-icon transition-all duration-300 transform" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<div className="md:hidden flex items-center space-x-2">
|
||||
<button
|
||||
onClick={toggleMobileMenu}
|
||||
className="p-2 text-gray-700 dark:text-gray-300 hover:text-blue-600 transition-colors"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation Menu */}
|
||||
{mobileMenuOpen && (
|
||||
<div className="md:hidden bg-white dark:bg-gray-900 border-t dark:border-gray-700">
|
||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
||||
<a href="#hero" className="bg-blue-50 dark:bg-blue-900 text-blue-600 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.home}
|
||||
</a>
|
||||
<a href="#services" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.services}
|
||||
</a>
|
||||
<a href="#portfolio" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.portfolio}
|
||||
</a>
|
||||
<a href="#calculator" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.calculator}
|
||||
</a>
|
||||
<a href="#contact" className="text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">
|
||||
{t.navigation.contact}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Hero */}
|
||||
<section id="hero" className="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div className="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
{/* Animated blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div className="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div className="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
{t.hero.title.smart} <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">{t.hero.title.solutions}</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.hero.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#contact" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
{t.hero.cta.start}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.hero.cta.portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="absolute bottom-20 left-1/2 -translate-x-1/2 animate-bounce">
|
||||
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section id="services" className="py-20 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.hero.title} <span className="text-yellow-300">{t.services.hero.title_highlight}</span>
|
||||
</h2>
|
||||
<p className="text-xl md:text-2xl mb-8 text-gray-700 dark:text-gray-300">
|
||||
{t.services.hero.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Services Grid */}
|
||||
<div className="space-y-12">
|
||||
{services.map((service, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={index * 150}
|
||||
>
|
||||
{/* Background with Gradient */}
|
||||
<div className={`relative h-64 overflow-hidden ${
|
||||
index % 4 === 0 ? 'bg-gradient-to-r from-blue-600 to-purple-600' :
|
||||
index % 4 === 1 ? 'bg-gradient-to-r from-green-500 to-teal-600' :
|
||||
index % 4 === 2 ? 'bg-gradient-to-r from-purple-600 to-pink-600' :
|
||||
'bg-gradient-to-r from-orange-500 to-red-600'
|
||||
}`}>
|
||||
|
||||
{/* Service Image/Icon Area */}
|
||||
<div className="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div className="relative z-10 text-white">
|
||||
{service.icon}
|
||||
{/* Decorative elements */}
|
||||
<div className="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div className="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style={{animationDelay: '1s'}}></div>
|
||||
</div>
|
||||
|
||||
{/* Gradient fade to center */}
|
||||
<div className="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
{/* Service Content Area */}
|
||||
<div className="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div className="text-right w-full text-white">
|
||||
|
||||
{/* Service Category Badge */}
|
||||
<div className="inline-block mb-4">
|
||||
<span className="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
{service.category}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Service Title */}
|
||||
<h3 className="text-3xl font-bold mb-4 leading-tight">
|
||||
{service.title}
|
||||
</h3>
|
||||
|
||||
{/* Service Description */}
|
||||
<p className="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
{service.description}
|
||||
</p>
|
||||
|
||||
{/* Pricing */}
|
||||
<div className="mb-6">
|
||||
<div className="text-white text-opacity-75 text-sm mb-1">{t.services.cards.starting_price}</div>
|
||||
<div className="text-3xl font-bold text-white">
|
||||
{service.price}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col gap-3 items-end">
|
||||
<a href="#calculator"
|
||||
className="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
{t.services.cards.calculate_cost}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Process Section */}
|
||||
<div className="mt-32">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.services.process.title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-700 dark:text-gray-300 text-center mb-12 max-w-3xl mx-auto">
|
||||
{t.services.process.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{/* Step 1 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div className="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step1.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step1.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 2 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div className="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step2.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step2.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 3 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div className="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step3.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step3.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 4 */}
|
||||
<div className="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div className="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span className="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">{t.services.process.step4.title}</h3>
|
||||
<p className="text-gray-700 dark:text-gray-300 text-center">
|
||||
{t.services.process.step4.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Why Choose Us Section */}
|
||||
<div className="mt-32">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
{/* Content */}
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.services.why_choose.title}
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Feature 1 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Rocket className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.modern_tech.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.modern_tech.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 2 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Users className="w-6 h-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.expert_team.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.expert_team.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 3 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Clock className="w-6 h-6 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.fast_response.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.fast_response.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Feature 4 */}
|
||||
<div className="flex items-start">
|
||||
<div className="w-12 h-12 bg-orange-100 dark:bg-orange-900 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<Headphones className="w-6 h-6 text-orange-600 dark:text-orange-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t.services.why_choose.continuous_support.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.continuous_support.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image/Visual */}
|
||||
<div className="relative" data-aos="fade-left">
|
||||
<div className="bg-gradient-to-br from-blue-100 to-purple-100 dark:from-blue-900 dark:to-purple-900 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<Award className="w-24 h-24 text-blue-600 dark:text-blue-400 mx-auto mb-4" />
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">{t.services.why_choose.quality_guarantee.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
{t.services.why_choose.quality_guarantee.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Portfolio */}
|
||||
<section id="portfolio" className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16" data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
{t.portfolio.title.recent} <span className="text-purple-600 dark:text-purple-400">{t.portfolio.title.projects}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-3xl mx-auto">
|
||||
{t.portfolio.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{demoPortfolio.map((project, index) => (
|
||||
<div key={project._id} className="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" data-aos="fade-up" data-aos-delay={index * 100}>
|
||||
<div className="relative overflow-hidden">
|
||||
<img src={project.images?.[0]?.url} alt={project.title} className="w-full h-48 object-cover" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies?.slice(0, 3).map((tech) => (
|
||||
<span key={tech} className="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium">{project.category}</span>
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm flex items-center"><Eye className="w-4 h-4 mr-1" />{project.viewCount ?? 0}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">{project.title}</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">{project.shortDescription ?? project.description}</p>
|
||||
<a href="#" className="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
{t.common.view_details}
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-12" data-aos="fade-up">
|
||||
<a href="#portfolio" className="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
{t.portfolio.view_all}
|
||||
<ArrowRight className="ml-2 w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Calculator CTA */}
|
||||
<section id="calculator" className="py-20 cta-section">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-white mb-6">{t.calculator.cta.title}</h2>
|
||||
<p className="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">{t.calculator.cta.subtitle}</p>
|
||||
<a href="#calculator" className="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<Calculator className="mr-3" />
|
||||
{t.calculator.cta.button}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services CTA */}
|
||||
<section className="py-20 bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
{t.services.cta.title}
|
||||
</h2>
|
||||
<p className="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
{t.services.cta.subtitle}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="#calculator" className="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
{t.services.cta.calculate_cost}
|
||||
</a>
|
||||
<a href="#portfolio" className="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
{t.services.cta.view_portfolio}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact */}
|
||||
<section id="contact" className="py-20 bg-white dark:bg-gray-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t.contact.cta.ready} <span className="text-blue-600 dark:text-blue-400">{t.contact.cta.start}</span>
|
||||
{t.contact.cta.question}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">{t.contact.cta.subtitle}</p>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<Phone className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.phone.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.phone.number}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<Mail className="w-6 h-6 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.email.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.email.address}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<MessageCircle className="w-6 h-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white">{t.contact.telegram.title}</div>
|
||||
<div className="text-gray-600 dark:text-gray-300">{t.contact.telegram.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-aos="fade-left">
|
||||
<div className="p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">{t.contact.form.title}</h3>
|
||||
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={t.contact.form.name}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<input
|
||||
type="email"
|
||||
placeholder={t.contact.form.email}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<input
|
||||
type="tel"
|
||||
placeholder={t.contact.form.phone}
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
/>
|
||||
<select
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
|
||||
title={t.contact.form.service.select}
|
||||
>
|
||||
<option value="">{t.contact.form.service.select}</option>
|
||||
<option value="web">{t.contact.form.service.web}</option>
|
||||
<option value="mobile">{t.contact.form.service.mobile}</option>
|
||||
<option value="design">{t.contact.form.service.design}</option>
|
||||
<option value="branding">{t.contact.form.service.branding}</option>
|
||||
<option value="consulting">{t.contact.form.service.consulting}</option>
|
||||
<option value="other">{t.contact.form.service.other}</option>
|
||||
</select>
|
||||
<textarea
|
||||
rows={4}
|
||||
placeholder={t.contact.form.message}
|
||||
required
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"
|
||||
></textarea>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105"
|
||||
>
|
||||
{t.contact.form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
256
.history/views/admin-bundle-comparison_20251026211814.ejs
Normal file
256
.history/views/admin-bundle-comparison_20251026211814.ejs
Normal file
@@ -0,0 +1,256 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Bundle Comparison - SmartSolTech</title>
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50">
|
||||
<div class="min-h-screen py-12">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center mb-12">
|
||||
<h1 class="text-4xl font-bold text-gray-900 mb-4">
|
||||
SmartSolTech Admin Bundle 비교
|
||||
</h1>
|
||||
<p class="text-lg text-gray-600 max-w-3xl mx-auto">
|
||||
우리 웹사이트에 가장 적합한 관리자 패널을 선택해보세요. 각 솔루션의 기능과 디자인을 비교해보실 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Admin Bundle Comparison -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
|
||||
<!-- AdminLTE Card -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
|
||||
<div class="p-6 bg-gradient-to-r from-blue-500 to-purple-600 text-white">
|
||||
<h2 class="text-2xl font-bold mb-2">AdminLTE 3</h2>
|
||||
<p class="text-blue-100">무료 오픈소스 관리자 템플릿</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
<div class="space-y-4 mb-6">
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>완전 무료 오픈소스</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>한국어 지원 우수</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>풍부한 컴포넌트</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>jQuery 기반 (안정성)</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>대규모 커뮤니티</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>Bootstrap 4/5 호환</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<h4 class="font-semibold mb-3">주요 기능:</h4>
|
||||
<ul class="text-sm text-gray-600 space-y-1">
|
||||
<li>• 반응형 대시보드</li>
|
||||
<li>• 다양한 차트와 위젯</li>
|
||||
<li>• 카드형 레이아웃</li>
|
||||
<li>• 사이드바 접기/펼치기</li>
|
||||
<li>• 어두운/밝은 테마</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<a href="/demo/demo-adminlte" target="_blank"
|
||||
class="flex-1 bg-blue-600 text-white text-center py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
<i class="fas fa-eye mr-2"></i>
|
||||
데모 보기
|
||||
</a>
|
||||
<a href="https://adminlte.io/" target="_blank"
|
||||
class="flex-1 bg-gray-200 text-gray-700 text-center py-3 rounded-lg hover:bg-gray-300 transition-colors">
|
||||
<i class="fas fa-external-link-alt mr-2"></i>
|
||||
공식 사이트
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabler Card -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
|
||||
<div class="p-6 bg-gradient-to-r from-purple-500 to-pink-600 text-white">
|
||||
<h2 class="text-2xl font-bold mb-2">Tabler</h2>
|
||||
<p class="text-purple-100">모던 관리자 대시보드 템플릿</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
<div class="space-y-4 mb-6">
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>모던한 디자인</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>빠른 성능</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>SVG 아이콘 시스템</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>Bootstrap 5 기반</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>TypeScript 지원</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>최신 웹 표준</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<h4 class="font-semibold mb-3">주요 기능:</h4>
|
||||
<ul class="text-sm text-gray-600 space-y-1">
|
||||
<li>• 깔끔한 미니멀 디자인</li>
|
||||
<li>• 3000+ 무료 SVG 아이콘</li>
|
||||
<li>• 드롭다운 메뉴</li>
|
||||
<li>• 모바일 최적화</li>
|
||||
<li>• 빠른 로딩 속도</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<a href="/demo/demo-tabler" target="_blank"
|
||||
class="flex-1 bg-purple-600 text-white text-center py-3 rounded-lg hover:bg-purple-700 transition-colors">
|
||||
<i class="fas fa-eye mr-2"></i>
|
||||
데모 보기
|
||||
</a>
|
||||
<a href="https://tabler.io/" target="_blank"
|
||||
class="flex-1 bg-gray-200 text-gray-700 text-center py-3 rounded-lg hover:bg-gray-300 transition-colors">
|
||||
<i class="fas fa-external-link-alt mr-2"></i>
|
||||
공식 사이트
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Comparison Table -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-12">
|
||||
<div class="p-6 bg-gradient-to-r from-gray-800 to-gray-900 text-white">
|
||||
<h3 class="text-xl font-bold">상세 비교표</h3>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">기능</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">AdminLTE</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tabler</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">가격</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">완전 무료</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">무료 + Pro 버전</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">한국어 지원</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">우수</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-yellow-600">보통</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">디자인</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">클래식</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-purple-600">모던</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">컴포넌트 수</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">매우 많음</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">적당함</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">성능</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">양호</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">우수</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">커뮤니티</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">대규모</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">성장중</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">학습 곡선</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">쉬움</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-yellow-600">보통</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recommendation -->
|
||||
<div class="bg-gradient-to-r from-green-400 to-blue-500 rounded-xl p-8 text-white">
|
||||
<div class="text-center">
|
||||
<h3 class="text-2xl font-bold mb-4">
|
||||
<i class="fas fa-thumbs-up mr-2"></i>
|
||||
추천 결과
|
||||
</h3>
|
||||
<p class="text-lg mb-6">
|
||||
SmartSolTech 웹사이트의 특성을 고려한 맞춤 추천
|
||||
</p>
|
||||
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-6 max-w-2xl mx-auto">
|
||||
<h4 class="text-xl font-semibold mb-3">
|
||||
🏆 AdminLTE 3 추천
|
||||
</h4>
|
||||
<p class="text-left">
|
||||
<strong>추천 이유:</strong><br>
|
||||
• 한국 고객을 위한 완벽한 한국어 지원<br>
|
||||
• 무료로 모든 기능 사용 가능<br>
|
||||
• 기존 시스템과의 호환성 우수<br>
|
||||
• 풍부한 문서화와 커뮤니티 지원<br>
|
||||
• 기업용 웹사이트에 적합한 안정적인 디자인
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Back to Main Site -->
|
||||
<div class="text-center mt-12">
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-900 transition-colors">
|
||||
<i class="fas fa-arrow-left mr-2"></i>
|
||||
메인 사이트로 돌아가기
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
256
.history/views/admin-bundle-comparison_20251026211849.ejs
Normal file
256
.history/views/admin-bundle-comparison_20251026211849.ejs
Normal file
@@ -0,0 +1,256 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Bundle Comparison - SmartSolTech</title>
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50">
|
||||
<div class="min-h-screen py-12">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center mb-12">
|
||||
<h1 class="text-4xl font-bold text-gray-900 mb-4">
|
||||
SmartSolTech Admin Bundle 비교
|
||||
</h1>
|
||||
<p class="text-lg text-gray-600 max-w-3xl mx-auto">
|
||||
우리 웹사이트에 가장 적합한 관리자 패널을 선택해보세요. 각 솔루션의 기능과 디자인을 비교해보실 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Admin Bundle Comparison -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
|
||||
<!-- AdminLTE Card -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
|
||||
<div class="p-6 bg-gradient-to-r from-blue-500 to-purple-600 text-white">
|
||||
<h2 class="text-2xl font-bold mb-2">AdminLTE 3</h2>
|
||||
<p class="text-blue-100">무료 오픈소스 관리자 템플릿</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
<div class="space-y-4 mb-6">
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>완전 무료 오픈소스</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>한국어 지원 우수</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>풍부한 컴포넌트</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>jQuery 기반 (안정성)</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>대규모 커뮤니티</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>Bootstrap 4/5 호환</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<h4 class="font-semibold mb-3">주요 기능:</h4>
|
||||
<ul class="text-sm text-gray-600 space-y-1">
|
||||
<li>• 반응형 대시보드</li>
|
||||
<li>• 다양한 차트와 위젯</li>
|
||||
<li>• 카드형 레이아웃</li>
|
||||
<li>• 사이드바 접기/펼치기</li>
|
||||
<li>• 어두운/밝은 테마</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<a href="/demo/demo-adminlte" target="_blank"
|
||||
class="flex-1 bg-blue-600 text-white text-center py-3 rounded-lg hover:bg-blue-700 transition-colors">
|
||||
<i class="fas fa-eye mr-2"></i>
|
||||
데모 보기
|
||||
</a>
|
||||
<a href="https://adminlte.io/" target="_blank"
|
||||
class="flex-1 bg-gray-200 text-gray-700 text-center py-3 rounded-lg hover:bg-gray-300 transition-colors">
|
||||
<i class="fas fa-external-link-alt mr-2"></i>
|
||||
공식 사이트
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabler Card -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
|
||||
<div class="p-6 bg-gradient-to-r from-purple-500 to-pink-600 text-white">
|
||||
<h2 class="text-2xl font-bold mb-2">Tabler</h2>
|
||||
<p class="text-purple-100">모던 관리자 대시보드 템플릿</p>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
<div class="space-y-4 mb-6">
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>모던한 디자인</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>빠른 성능</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-check-circle text-green-500 mr-3"></i>
|
||||
<span>SVG 아이콘 시스템</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>Bootstrap 5 기반</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>TypeScript 지원</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-star text-yellow-500 mr-3"></i>
|
||||
<span>최신 웹 표준</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<h4 class="font-semibold mb-3">주요 기능:</h4>
|
||||
<ul class="text-sm text-gray-600 space-y-1">
|
||||
<li>• 깔끔한 미니멀 디자인</li>
|
||||
<li>• 3000+ 무료 SVG 아이콘</li>
|
||||
<li>• 드롭다운 메뉴</li>
|
||||
<li>• 모바일 최적화</li>
|
||||
<li>• 빠른 로딩 속도</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<a href="/demo/demo-tabler" target="_blank"
|
||||
class="flex-1 bg-purple-600 text-white text-center py-3 rounded-lg hover:bg-purple-700 transition-colors">
|
||||
<i class="fas fa-eye mr-2"></i>
|
||||
데모 보기
|
||||
</a>
|
||||
<a href="https://tabler.io/" target="_blank"
|
||||
class="flex-1 bg-gray-200 text-gray-700 text-center py-3 rounded-lg hover:bg-gray-300 transition-colors">
|
||||
<i class="fas fa-external-link-alt mr-2"></i>
|
||||
공식 사이트
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Comparison Table -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-12">
|
||||
<div class="p-6 bg-gradient-to-r from-gray-800 to-gray-900 text-white">
|
||||
<h3 class="text-xl font-bold">상세 비교표</h3>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">기능</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">AdminLTE</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tabler</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">가격</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">완전 무료</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">무료 + Pro 버전</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">한국어 지원</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">우수</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-yellow-600">보통</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">디자인</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">클래식</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-purple-600">모던</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">컴포넌트 수</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">매우 많음</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">적당함</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">성능</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">양호</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">우수</td>
|
||||
</tr>
|
||||
<tr class="bg-gray-50">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">커뮤니티</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">대규모</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600">성장중</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">학습 곡선</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">쉬움</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-yellow-600">보통</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recommendation -->
|
||||
<div class="bg-gradient-to-r from-green-400 to-blue-500 rounded-xl p-8 text-white">
|
||||
<div class="text-center">
|
||||
<h3 class="text-2xl font-bold mb-4">
|
||||
<i class="fas fa-thumbs-up mr-2"></i>
|
||||
추천 결과
|
||||
</h3>
|
||||
<p class="text-lg mb-6">
|
||||
SmartSolTech 웹사이트의 특성을 고려한 맞춤 추천
|
||||
</p>
|
||||
|
||||
<div class="bg-white bg-opacity-20 rounded-lg p-6 max-w-2xl mx-auto">
|
||||
<h4 class="text-xl font-semibold mb-3">
|
||||
🏆 AdminLTE 3 추천
|
||||
</h4>
|
||||
<p class="text-left">
|
||||
<strong>추천 이유:</strong><br>
|
||||
• 한국 고객을 위한 완벽한 한국어 지원<br>
|
||||
• 무료로 모든 기능 사용 가능<br>
|
||||
• 기존 시스템과의 호환성 우수<br>
|
||||
• 풍부한 문서화와 커뮤니티 지원<br>
|
||||
• 기업용 웹사이트에 적합한 안정적인 디자인
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Back to Main Site -->
|
||||
<div class="text-center mt-12">
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 bg-gray-800 text-white rounded-lg hover:bg-gray-900 transition-colors">
|
||||
<i class="fas fa-arrow-left mr-2"></i>
|
||||
메인 사이트로 돌아가기
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
361
.history/views/admin/banner-editor_20251026215001.ejs
Normal file
361
.history/views/admin/banner-editor_20251026215001.ejs
Normal file
@@ -0,0 +1,361 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-images mr-2"></i>Редактор Баннеров</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Баннеры</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Banner Upload Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Загрузить новый баннер</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="upload-zone p-4 text-center border-2 border-dashed border-gray-300 rounded"
|
||||
ondrop="handleDrop(event)" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="h5 text-muted mb-2">Перетащите изображения сюда или нажмите для выбора</p>
|
||||
<p class="text-muted">Поддерживаются: JPG, PNG, GIF (максимум 10MB)</p>
|
||||
<input type="file" id="banner-upload" multiple accept="image/*" class="d-none">
|
||||
<button type="button" class="btn btn-primary mt-3" onclick="document.getElementById('banner-upload').click()">
|
||||
<i class="fas fa-plus mr-1"></i>Выбрать файлы
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Current Banners Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Текущие баннеры</h3>
|
||||
<div class="card-tools">
|
||||
<button class="btn btn-sm btn-default" onclick="loadBanners()">
|
||||
<i class="fas fa-sync-alt"></i> Обновить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="banners-list" class="row">
|
||||
<!-- Banners will be loaded here -->
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div id="empty-state" class="text-center py-5" style="display: none;">
|
||||
<i class="fas fa-images fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Нет загруженных баннеров</h4>
|
||||
<p class="text-muted">Загрузите ваши первые баннеры используя форму выше</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Banner Edit Modal -->
|
||||
<div class="modal fade" id="edit-banner-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Редактировать баннер</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="edit-banner-form">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="edit-banner-id">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<img id="edit-banner-preview" src="" alt="Banner preview" class="img-fluid rounded">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-title">Заголовок</label>
|
||||
<input type="text" class="form-control" id="edit-banner-title" name="title" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-subtitle">Подзаголовок</label>
|
||||
<input type="text" class="form-control" id="edit-banner-subtitle" name="subtitle">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-description">Описание</label>
|
||||
<textarea class="form-control" id="edit-banner-description" name="description" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-button-text">Текст кнопки</label>
|
||||
<input type="text" class="form-control" id="edit-banner-button-text" name="buttonText">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-button-url">Ссылка кнопки</label>
|
||||
<input type="url" class="form-control" id="edit-banner-button-url" name="buttonUrl">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="edit-banner-order" name="order" min="0">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="edit-banner-active" name="active">
|
||||
<label class="custom-control-label" for="edit-banner-active">Активен</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Отмена</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.upload-zone.dragover {
|
||||
border-color: #007bff !important;
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
.banner-item {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.banner-item:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let banners = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadBanners();
|
||||
|
||||
// Setup file upload
|
||||
document.getElementById('banner-upload').addEventListener('change', handleFileSelect);
|
||||
|
||||
// Setup edit form
|
||||
document.getElementById('edit-banner-form').addEventListener('submit', saveBanner);
|
||||
});
|
||||
|
||||
async function loadBanners() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/banners');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
banners = data.banners;
|
||||
renderBanners();
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading banners:', error);
|
||||
alert('Ошибка загрузки баннеров: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBanners() {
|
||||
const container = document.getElementById('banners-list');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
|
||||
if (banners.length === 0) {
|
||||
container.innerHTML = '';
|
||||
emptyState.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
emptyState.style.display = 'none';
|
||||
|
||||
container.innerHTML = banners.map(banner => `
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card banner-item">
|
||||
<img src="${banner.imageUrl}" class="card-img-top" style="height: 200px; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${banner.title || 'Без названия'}</h5>
|
||||
<p class="card-text text-muted small">${banner.subtitle || ''}</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="editBanner('${banner._id}')">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="deleteBanner('${banner._id}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<small class="text-muted">
|
||||
${banner.active ? '<span class="badge badge-success">Активен</span>' : '<span class="badge badge-secondary">Неактивен</span>'}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function handleDragOver(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.add('dragover');
|
||||
}
|
||||
|
||||
function handleDragLeave(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.remove('dragover');
|
||||
}
|
||||
|
||||
function handleDrop(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.remove('dragover');
|
||||
|
||||
const files = Array.from(event.dataTransfer.files);
|
||||
uploadFiles(files);
|
||||
}
|
||||
|
||||
function handleFileSelect(event) {
|
||||
const files = Array.from(event.target.files);
|
||||
uploadFiles(files);
|
||||
event.target.value = ''; // Reset input
|
||||
}
|
||||
|
||||
async function uploadFiles(files) {
|
||||
for (const file of files) {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
alert(`Файл ${file.name} не является изображением`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.size > 10 * 1024 * 1024) { // 10MB
|
||||
alert(`Файл ${file.name} слишком большой (максимум 10MB)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await uploadFile(file);
|
||||
}
|
||||
|
||||
loadBanners(); // Refresh the list
|
||||
}
|
||||
|
||||
async function uploadFile(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('banner', file);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/admin/banners/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
|
||||
console.log(`Файл ${file.name} успешно загружен`);
|
||||
} catch (error) {
|
||||
console.error(`Error uploading ${file.name}:`, error);
|
||||
alert(`Ошибка загрузки ${file.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function editBanner(bannerId) {
|
||||
const banner = banners.find(b => b._id === bannerId);
|
||||
if (!banner) return;
|
||||
|
||||
// Fill the form
|
||||
document.getElementById('edit-banner-id').value = banner._id;
|
||||
document.getElementById('edit-banner-preview').src = banner.imageUrl;
|
||||
document.getElementById('edit-banner-title').value = banner.title || '';
|
||||
document.getElementById('edit-banner-subtitle').value = banner.subtitle || '';
|
||||
document.getElementById('edit-banner-description').value = banner.description || '';
|
||||
document.getElementById('edit-banner-button-text').value = banner.buttonText || '';
|
||||
document.getElementById('edit-banner-button-url').value = banner.buttonUrl || '';
|
||||
document.getElementById('edit-banner-order').value = banner.order || 0;
|
||||
document.getElementById('edit-banner-active').checked = banner.active || false;
|
||||
|
||||
// Show modal
|
||||
$('#edit-banner-modal').modal('show');
|
||||
}
|
||||
|
||||
async function saveBanner(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const bannerId = document.getElementById('edit-banner-id').value;
|
||||
|
||||
const bannerData = {
|
||||
title: formData.get('title'),
|
||||
subtitle: formData.get('subtitle'),
|
||||
description: formData.get('description'),
|
||||
buttonText: formData.get('buttonText'),
|
||||
buttonUrl: formData.get('buttonUrl'),
|
||||
order: parseInt(formData.get('order')) || 0,
|
||||
active: formData.has('active')
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/banners/${bannerId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(bannerData)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
$('#edit-banner-modal').modal('hide');
|
||||
loadBanners();
|
||||
alert('Баннер обновлен');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving banner:', error);
|
||||
alert('Ошибка сохранения баннера: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteBanner(bannerId) {
|
||||
if (!confirm('Вы уверены, что хотите удалить этот баннер?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/banners/${bannerId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
loadBanners();
|
||||
alert('Баннер удален');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting banner:', error);
|
||||
alert('Ошибка удаления баннера: ' + error.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
361
.history/views/admin/banner-editor_20251026215051.ejs
Normal file
361
.history/views/admin/banner-editor_20251026215051.ejs
Normal file
@@ -0,0 +1,361 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-images mr-2"></i>Редактор Баннеров</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Баннеры</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Banner Upload Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Загрузить новый баннер</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="upload-zone p-4 text-center border-2 border-dashed border-gray-300 rounded"
|
||||
ondrop="handleDrop(event)" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="h5 text-muted mb-2">Перетащите изображения сюда или нажмите для выбора</p>
|
||||
<p class="text-muted">Поддерживаются: JPG, PNG, GIF (максимум 10MB)</p>
|
||||
<input type="file" id="banner-upload" multiple accept="image/*" class="d-none">
|
||||
<button type="button" class="btn btn-primary mt-3" onclick="document.getElementById('banner-upload').click()">
|
||||
<i class="fas fa-plus mr-1"></i>Выбрать файлы
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Current Banners Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Текущие баннеры</h3>
|
||||
<div class="card-tools">
|
||||
<button class="btn btn-sm btn-default" onclick="loadBanners()">
|
||||
<i class="fas fa-sync-alt"></i> Обновить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="banners-list" class="row">
|
||||
<!-- Banners will be loaded here -->
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div id="empty-state" class="text-center py-5" style="display: none;">
|
||||
<i class="fas fa-images fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Нет загруженных баннеров</h4>
|
||||
<p class="text-muted">Загрузите ваши первые баннеры используя форму выше</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Banner Edit Modal -->
|
||||
<div class="modal fade" id="edit-banner-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Редактировать баннер</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="edit-banner-form">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="edit-banner-id">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<img id="edit-banner-preview" src="" alt="Banner preview" class="img-fluid rounded">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-title">Заголовок</label>
|
||||
<input type="text" class="form-control" id="edit-banner-title" name="title" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-subtitle">Подзаголовок</label>
|
||||
<input type="text" class="form-control" id="edit-banner-subtitle" name="subtitle">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-description">Описание</label>
|
||||
<textarea class="form-control" id="edit-banner-description" name="description" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-button-text">Текст кнопки</label>
|
||||
<input type="text" class="form-control" id="edit-banner-button-text" name="buttonText">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-button-url">Ссылка кнопки</label>
|
||||
<input type="url" class="form-control" id="edit-banner-button-url" name="buttonUrl">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-banner-order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="edit-banner-order" name="order" min="0">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="edit-banner-active" name="active">
|
||||
<label class="custom-control-label" for="edit-banner-active">Активен</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Отмена</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.upload-zone.dragover {
|
||||
border-color: #007bff !important;
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
.banner-item {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.banner-item:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let banners = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadBanners();
|
||||
|
||||
// Setup file upload
|
||||
document.getElementById('banner-upload').addEventListener('change', handleFileSelect);
|
||||
|
||||
// Setup edit form
|
||||
document.getElementById('edit-banner-form').addEventListener('submit', saveBanner);
|
||||
});
|
||||
|
||||
async function loadBanners() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/banners');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
banners = data.banners;
|
||||
renderBanners();
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading banners:', error);
|
||||
alert('Ошибка загрузки баннеров: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBanners() {
|
||||
const container = document.getElementById('banners-list');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
|
||||
if (banners.length === 0) {
|
||||
container.innerHTML = '';
|
||||
emptyState.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
emptyState.style.display = 'none';
|
||||
|
||||
container.innerHTML = banners.map(banner => `
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card banner-item">
|
||||
<img src="${banner.imageUrl}" class="card-img-top" style="height: 200px; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${banner.title || 'Без названия'}</h5>
|
||||
<p class="card-text text-muted small">${banner.subtitle || ''}</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="editBanner('${banner._id}')">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="deleteBanner('${banner._id}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<small class="text-muted">
|
||||
${banner.active ? '<span class="badge badge-success">Активен</span>' : '<span class="badge badge-secondary">Неактивен</span>'}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function handleDragOver(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.add('dragover');
|
||||
}
|
||||
|
||||
function handleDragLeave(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.remove('dragover');
|
||||
}
|
||||
|
||||
function handleDrop(event) {
|
||||
event.preventDefault();
|
||||
event.currentTarget.classList.remove('dragover');
|
||||
|
||||
const files = Array.from(event.dataTransfer.files);
|
||||
uploadFiles(files);
|
||||
}
|
||||
|
||||
function handleFileSelect(event) {
|
||||
const files = Array.from(event.target.files);
|
||||
uploadFiles(files);
|
||||
event.target.value = ''; // Reset input
|
||||
}
|
||||
|
||||
async function uploadFiles(files) {
|
||||
for (const file of files) {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
alert(`Файл ${file.name} не является изображением`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.size > 10 * 1024 * 1024) { // 10MB
|
||||
alert(`Файл ${file.name} слишком большой (максимум 10MB)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await uploadFile(file);
|
||||
}
|
||||
|
||||
loadBanners(); // Refresh the list
|
||||
}
|
||||
|
||||
async function uploadFile(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('banner', file);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/admin/banners/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
|
||||
console.log(`Файл ${file.name} успешно загружен`);
|
||||
} catch (error) {
|
||||
console.error(`Error uploading ${file.name}:`, error);
|
||||
alert(`Ошибка загрузки ${file.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function editBanner(bannerId) {
|
||||
const banner = banners.find(b => b._id === bannerId);
|
||||
if (!banner) return;
|
||||
|
||||
// Fill the form
|
||||
document.getElementById('edit-banner-id').value = banner._id;
|
||||
document.getElementById('edit-banner-preview').src = banner.imageUrl;
|
||||
document.getElementById('edit-banner-title').value = banner.title || '';
|
||||
document.getElementById('edit-banner-subtitle').value = banner.subtitle || '';
|
||||
document.getElementById('edit-banner-description').value = banner.description || '';
|
||||
document.getElementById('edit-banner-button-text').value = banner.buttonText || '';
|
||||
document.getElementById('edit-banner-button-url').value = banner.buttonUrl || '';
|
||||
document.getElementById('edit-banner-order').value = banner.order || 0;
|
||||
document.getElementById('edit-banner-active').checked = banner.active || false;
|
||||
|
||||
// Show modal
|
||||
$('#edit-banner-modal').modal('show');
|
||||
}
|
||||
|
||||
async function saveBanner(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const bannerId = document.getElementById('edit-banner-id').value;
|
||||
|
||||
const bannerData = {
|
||||
title: formData.get('title'),
|
||||
subtitle: formData.get('subtitle'),
|
||||
description: formData.get('description'),
|
||||
buttonText: formData.get('buttonText'),
|
||||
buttonUrl: formData.get('buttonUrl'),
|
||||
order: parseInt(formData.get('order')) || 0,
|
||||
active: formData.has('active')
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/banners/${bannerId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(bannerData)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
$('#edit-banner-modal').modal('hide');
|
||||
loadBanners();
|
||||
alert('Баннер обновлен');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving banner:', error);
|
||||
alert('Ошибка сохранения баннера: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteBanner(bannerId) {
|
||||
if (!confirm('Вы уверены, что хотите удалить этот баннер?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/banners/${bannerId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
loadBanners();
|
||||
alert('Баннер удален');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting banner:', error);
|
||||
alert('Ошибка удаления баннера: ' + error.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
359
.history/views/admin/dashboard-adminlte_20251026211437.ejs
Normal file
359
.history/views/admin/dashboard-adminlte_20251026211437.ejs
Normal file
@@ -0,0 +1,359 @@
|
||||
<!-- Dashboard Content -->
|
||||
<div class="row">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info elevation-1">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">포트폴리오 프로젝트</span>
|
||||
<span class="info-box-number"><%= stats.portfolioCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-info" style="width: 70%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
70% 완료된 프로젝트
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-success elevation-1">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">제공 서비스</span>
|
||||
<span class="info-box-number"><%= stats.servicesCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 서비스 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-warning elevation-1">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">문의 메시지</span>
|
||||
<span class="info-box-number"><%= stats.contactsCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-warning" style="width: 60%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
60% 응답 완료
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-danger elevation-1">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">관리자 계정</span>
|
||||
<span class="info-box-number"><%= stats.usersCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 계정 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Row -->
|
||||
<div class="row">
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-briefcase mr-1"></i>
|
||||
최근 포트폴리오 프로젝트
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentPortfolio.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-info badge-pill">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= project.title %></h6>
|
||||
<p class="text-muted mb-1"><%= project.category %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-calendar mr-1"></i>
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= project.status === 'completed' ? 'success' : project.status === 'in-progress' ? 'warning' : 'secondary' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-eye mr-1"></i>
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-briefcase fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">아직 포트폴리오 프로젝트가 없습니다.</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
첫 번째 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-envelope mr-1"></i>
|
||||
최근 문의 메시지
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentContacts.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= contact.name %></h6>
|
||||
<p class="text-muted mb-1"><%= contact.email %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-clock mr-1"></i>
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= contact.status === 'replied' ? 'success' : contact.status === 'pending' ? 'warning' : 'secondary' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm">
|
||||
<i class="fas fa-envelope-open mr-1"></i>
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-envelope fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">새로운 문의가 없습니다.</p>
|
||||
<small class="text-muted">고객 문의가 들어오면 여기에 표시됩니다.</small>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions & Tools -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-bolt mr-1"></i>
|
||||
빠른 작업
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-info">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">새 프로젝트</span>
|
||||
<span class="info-box-number">추가하기</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/portfolio/add" class="progress-description text-white">
|
||||
포트폴리오에 새 프로젝트 추가 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-success">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">서비스 관리</span>
|
||||
<span class="info-box-number">설정</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/services" class="progress-description text-white">
|
||||
서비스 가격 및 내용 수정 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-warning">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">미디어</span>
|
||||
<span class="info-box-number">업로드</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/media" class="progress-description text-white">
|
||||
이미지 및 파일 관리 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-danger">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-wrench"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">사이트 설정</span>
|
||||
<span class="info-box-number">관리</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/settings" class="progress-description text-white">
|
||||
전체 사이트 설정 변경 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-server mr-1"></i>
|
||||
시스템 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-caret-up"></i> 99.2%
|
||||
</span>
|
||||
<h5 class="description-header">서버 업타임</h5>
|
||||
<span class="description-text">지난 30일</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-caret-up"></i> 2.3초
|
||||
</span>
|
||||
<h5 class="description-header">평균 응답시간</h5>
|
||||
<span class="description-text">페이지 로딩</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 봇 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-check-circle"></i> 연결됨
|
||||
</span>
|
||||
<h5 class="description-header">봇 상태</h5>
|
||||
<span class="description-text">정상 작동</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-paper-plane"></i> 24개
|
||||
</span>
|
||||
<h5 class="description-header">전송된 알림</h5>
|
||||
<span class="description-text">오늘</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/admin/telegram" class="btn btn-success btn-sm">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
359
.history/views/admin/dashboard-adminlte_20251026211450.ejs
Normal file
359
.history/views/admin/dashboard-adminlte_20251026211450.ejs
Normal file
@@ -0,0 +1,359 @@
|
||||
<!-- Dashboard Content -->
|
||||
<div class="row">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info elevation-1">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">포트폴리오 프로젝트</span>
|
||||
<span class="info-box-number"><%= stats.portfolioCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-info" style="width: 70%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
70% 완료된 프로젝트
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-success elevation-1">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">제공 서비스</span>
|
||||
<span class="info-box-number"><%= stats.servicesCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 서비스 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-warning elevation-1">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">문의 메시지</span>
|
||||
<span class="info-box-number"><%= stats.contactsCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-warning" style="width: 60%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
60% 응답 완료
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-danger elevation-1">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">관리자 계정</span>
|
||||
<span class="info-box-number"><%= stats.usersCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 계정 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Row -->
|
||||
<div class="row">
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-briefcase mr-1"></i>
|
||||
최근 포트폴리오 프로젝트
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentPortfolio.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-info badge-pill">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= project.title %></h6>
|
||||
<p class="text-muted mb-1"><%= project.category %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-calendar mr-1"></i>
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= project.status === 'completed' ? 'success' : project.status === 'in-progress' ? 'warning' : 'secondary' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-eye mr-1"></i>
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-briefcase fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">아직 포트폴리오 프로젝트가 없습니다.</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
첫 번째 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-envelope mr-1"></i>
|
||||
최근 문의 메시지
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentContacts.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= contact.name %></h6>
|
||||
<p class="text-muted mb-1"><%= contact.email %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-clock mr-1"></i>
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= contact.status === 'replied' ? 'success' : contact.status === 'pending' ? 'warning' : 'secondary' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm">
|
||||
<i class="fas fa-envelope-open mr-1"></i>
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-envelope fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">새로운 문의가 없습니다.</p>
|
||||
<small class="text-muted">고객 문의가 들어오면 여기에 표시됩니다.</small>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions & Tools -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-bolt mr-1"></i>
|
||||
빠른 작업
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-info">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">새 프로젝트</span>
|
||||
<span class="info-box-number">추가하기</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/portfolio/add" class="progress-description text-white">
|
||||
포트폴리오에 새 프로젝트 추가 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-success">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">서비스 관리</span>
|
||||
<span class="info-box-number">설정</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/services" class="progress-description text-white">
|
||||
서비스 가격 및 내용 수정 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-warning">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">미디어</span>
|
||||
<span class="info-box-number">업로드</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/media" class="progress-description text-white">
|
||||
이미지 및 파일 관리 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-danger">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-wrench"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">사이트 설정</span>
|
||||
<span class="info-box-number">관리</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/settings" class="progress-description text-white">
|
||||
전체 사이트 설정 변경 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-server mr-1"></i>
|
||||
시스템 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-caret-up"></i> 99.2%
|
||||
</span>
|
||||
<h5 class="description-header">서버 업타임</h5>
|
||||
<span class="description-text">지난 30일</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-caret-up"></i> 2.3초
|
||||
</span>
|
||||
<h5 class="description-header">평균 응답시간</h5>
|
||||
<span class="description-text">페이지 로딩</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 봇 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-check-circle"></i> 연결됨
|
||||
</span>
|
||||
<h5 class="description-header">봇 상태</h5>
|
||||
<span class="description-text">정상 작동</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-paper-plane"></i> 24개
|
||||
</span>
|
||||
<h5 class="description-header">전송된 알림</h5>
|
||||
<span class="description-text">오늘</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/admin/telegram" class="btn btn-success btn-sm">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
342
.history/views/admin/dashboard-tabler_20251026211643.ejs
Normal file
342
.history/views/admin/dashboard-tabler_20251026211643.ejs
Normal file
@@ -0,0 +1,342 @@
|
||||
<!-- Tabler Dashboard -->
|
||||
<div class="row row-deck row-cards">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-12">
|
||||
<div class="row row-cards">
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-primary text-white avatar">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
포트폴리오 프로젝트
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.portfolioCount || 0 %>개 프로젝트
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-green text-white avatar">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
제공 서비스
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.servicesCount || 0 %>개 서비스
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-yellow text-white avatar">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
문의 메시지
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.contactsCount || 0 %>개 메시지
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-red text-white avatar">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
관리자 계정
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.usersCount || 0 %>명 사용자
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">최근 포트폴리오 프로젝트</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<div class="divide-y">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<div class="row <%= index < recentPortfolio.length - 1 ? 'py-2' : 'pt-2' %>">
|
||||
<div class="col-auto">
|
||||
<span class="avatar avatar-sm bg-blue-lt">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-truncate">
|
||||
<strong><%= project.title %></strong>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= project.category %> •
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<span class="badge bg-<%= project.status === 'completed' ? 'green' : project.status === 'in-progress' ? 'yellow' : 'blue' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm w-100">
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="empty">
|
||||
<div class="empty-img">
|
||||
<i class="fas fa-briefcase fa-3x text-muted"></i>
|
||||
</div>
|
||||
<p class="empty-title">포트폴리오가 없습니다</p>
|
||||
<p class="empty-subtitle text-muted">
|
||||
첫 번째 프로젝트를 추가해보세요
|
||||
</p>
|
||||
<div class="empty-action">
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i>
|
||||
프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">최근 문의 메시지</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<div class="divide-y">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<div class="row <%= index < recentContacts.length - 1 ? 'py-2' : 'pt-2' %>">
|
||||
<div class="col-auto">
|
||||
<span class="avatar avatar-sm">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-truncate">
|
||||
<strong><%= contact.name %></strong>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= contact.email %> •
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<span class="badge bg-<%= contact.status === 'replied' ? 'green' : contact.status === 'pending' ? 'yellow' : 'blue' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm w-100">
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="empty">
|
||||
<div class="empty-img">
|
||||
<i class="fas fa-envelope fa-3x text-muted"></i>
|
||||
</div>
|
||||
<p class="empty-title">새로운 문의가 없습니다</p>
|
||||
<p class="empty-subtitle text-muted">
|
||||
고객 문의가 들어오면 여기에 표시됩니다
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">빠른 작업</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/portfolio/add" class="card card-link bg-primary-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-primary mb-3">
|
||||
<i class="fas fa-plus fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">새 프로젝트</div>
|
||||
<div class="text-muted">포트폴리오에 추가</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/services" class="card card-link bg-green-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-green mb-3">
|
||||
<i class="fas fa-cog fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">서비스 관리</div>
|
||||
<div class="text-muted">가격 및 내용 수정</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/media" class="card card-link bg-yellow-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-yellow mb-3">
|
||||
<i class="fas fa-images fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">미디어 업로드</div>
|
||||
<div class="text-muted">이미지 및 파일 관리</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/settings" class="card card-link bg-red-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-red mb-3">
|
||||
<i class="fas fa-wrench fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">사이트 설정</div>
|
||||
<div class="text-muted">전체 설정 관리</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status & Analytics -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">시스템 상태</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-server fa-2x text-green"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">99.2%</div>
|
||||
<div class="text-muted">서버 업타임</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-clock fa-2x text-blue"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">2.3초</div>
|
||||
<div class="text-muted">평균 응답시간</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Telegram Bot Status -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">텔레그램 봇</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fab fa-telegram fa-2x text-green"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0 text-green">연결됨</div>
|
||||
<div class="text-muted">봇 상태</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-paper-plane fa-2x text-blue"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">24</div>
|
||||
<div class="text-muted">오늘 전송</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/telegram" class="btn btn-outline-primary w-100">
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
342
.history/views/admin/dashboard-tabler_20251026211716.ejs
Normal file
342
.history/views/admin/dashboard-tabler_20251026211716.ejs
Normal file
@@ -0,0 +1,342 @@
|
||||
<!-- Tabler Dashboard -->
|
||||
<div class="row row-deck row-cards">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-12">
|
||||
<div class="row row-cards">
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-primary text-white avatar">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
포트폴리오 프로젝트
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.portfolioCount || 0 %>개 프로젝트
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-green text-white avatar">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
제공 서비스
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.servicesCount || 0 %>개 서비스
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-yellow text-white avatar">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
문의 메시지
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.contactsCount || 0 %>개 메시지
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-red text-white avatar">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
관리자 계정
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= stats.usersCount || 0 %>명 사용자
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">최근 포트폴리오 프로젝트</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<div class="divide-y">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<div class="row <%= index < recentPortfolio.length - 1 ? 'py-2' : 'pt-2' %>">
|
||||
<div class="col-auto">
|
||||
<span class="avatar avatar-sm bg-blue-lt">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-truncate">
|
||||
<strong><%= project.title %></strong>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= project.category %> •
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<span class="badge bg-<%= project.status === 'completed' ? 'green' : project.status === 'in-progress' ? 'yellow' : 'blue' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm w-100">
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="empty">
|
||||
<div class="empty-img">
|
||||
<i class="fas fa-briefcase fa-3x text-muted"></i>
|
||||
</div>
|
||||
<p class="empty-title">포트폴리오가 없습니다</p>
|
||||
<p class="empty-subtitle text-muted">
|
||||
첫 번째 프로젝트를 추가해보세요
|
||||
</p>
|
||||
<div class="empty-action">
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i>
|
||||
프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">최근 문의 메시지</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<div class="divide-y">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<div class="row <%= index < recentContacts.length - 1 ? 'py-2' : 'pt-2' %>">
|
||||
<div class="col-auto">
|
||||
<span class="avatar avatar-sm">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-truncate">
|
||||
<strong><%= contact.name %></strong>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<%= contact.email %> •
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<span class="badge bg-<%= contact.status === 'replied' ? 'green' : contact.status === 'pending' ? 'yellow' : 'blue' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm w-100">
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="empty">
|
||||
<div class="empty-img">
|
||||
<i class="fas fa-envelope fa-3x text-muted"></i>
|
||||
</div>
|
||||
<p class="empty-title">새로운 문의가 없습니다</p>
|
||||
<p class="empty-subtitle text-muted">
|
||||
고객 문의가 들어오면 여기에 표시됩니다
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">빠른 작업</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/portfolio/add" class="card card-link bg-primary-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-primary mb-3">
|
||||
<i class="fas fa-plus fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">새 프로젝트</div>
|
||||
<div class="text-muted">포트폴리오에 추가</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/services" class="card card-link bg-green-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-green mb-3">
|
||||
<i class="fas fa-cog fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">서비스 관리</div>
|
||||
<div class="text-muted">가격 및 내용 수정</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/media" class="card card-link bg-yellow-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-yellow mb-3">
|
||||
<i class="fas fa-images fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">미디어 업로드</div>
|
||||
<div class="text-muted">이미지 및 파일 관리</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<a href="/admin/settings" class="card card-link bg-red-lt">
|
||||
<div class="card-body text-center">
|
||||
<div class="text-red mb-3">
|
||||
<i class="fas fa-wrench fa-2x"></i>
|
||||
</div>
|
||||
<div class="font-weight-medium">사이트 설정</div>
|
||||
<div class="text-muted">전체 설정 관리</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status & Analytics -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">시스템 상태</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-server fa-2x text-green"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">99.2%</div>
|
||||
<div class="text-muted">서버 업타임</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-clock fa-2x text-blue"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">2.3초</div>
|
||||
<div class="text-muted">평균 응답시간</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Telegram Bot Status -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">텔레그램 봇</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fab fa-telegram fa-2x text-green"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0 text-green">연결됨</div>
|
||||
<div class="text-muted">봇 상태</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<i class="fas fa-paper-plane fa-2x text-blue"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="h4 mb-0">24</div>
|
||||
<div class="text-muted">오늘 전송</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/admin/telegram" class="btn btn-outline-primary w-100">
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
360
.history/views/admin/dashboard_20251026212530.ejs
Normal file
360
.history/views/admin/dashboard_20251026212530.ejs
Normal file
@@ -0,0 +1,360 @@
|
||||
|
||||
<!-- Dashboard Content -->
|
||||
<div class="row">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info elevation-1">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">포트폴리오 프로젝트</span>
|
||||
<span class="info-box-number"><%= stats.portfolioCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-info" style="width: 70%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
70% 완료된 프로젝트
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-success elevation-1">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">제공 서비스</span>
|
||||
<span class="info-box-number"><%= stats.servicesCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 서비스 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-warning elevation-1">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">문의 메시지</span>
|
||||
<span class="info-box-number"><%= stats.contactsCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-warning" style="width: 60%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
60% 응답 완료
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-danger elevation-1">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">관리자 계정</span>
|
||||
<span class="info-box-number"><%= stats.usersCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 계정 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Row -->
|
||||
<div class="row">
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-briefcase mr-1"></i>
|
||||
최근 포트폴리오 프로젝트
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentPortfolio.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-info badge-pill">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= project.title %></h6>
|
||||
<p class="text-muted mb-1"><%= project.category %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-calendar mr-1"></i>
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= project.status === 'completed' ? 'success' : project.status === 'in-progress' ? 'warning' : 'secondary' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-eye mr-1"></i>
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-briefcase fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">아직 포트폴리오 프로젝트가 없습니다.</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
첫 번째 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-envelope mr-1"></i>
|
||||
최근 문의 메시지
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentContacts.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= contact.name %></h6>
|
||||
<p class="text-muted mb-1"><%= contact.email %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-clock mr-1"></i>
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= contact.status === 'replied' ? 'success' : contact.status === 'pending' ? 'warning' : 'secondary' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm">
|
||||
<i class="fas fa-envelope-open mr-1"></i>
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-envelope fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">새로운 문의가 없습니다.</p>
|
||||
<small class="text-muted">고객 문의가 들어오면 여기에 표시됩니다.</small>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions & Tools -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-bolt mr-1"></i>
|
||||
빠른 작업
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-info">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">새 프로젝트</span>
|
||||
<span class="info-box-number">추가하기</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/portfolio/add" class="progress-description text-white">
|
||||
포트폴리오에 새 프로젝트 추가 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-success">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">서비스 관리</span>
|
||||
<span class="info-box-number">설정</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/services" class="progress-description text-white">
|
||||
서비스 가격 및 내용 수정 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-warning">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">미디어</span>
|
||||
<span class="info-box-number">업로드</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/media" class="progress-description text-white">
|
||||
이미지 및 파일 관리 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-danger">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-wrench"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">사이트 설정</span>
|
||||
<span class="info-box-number">관리</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/settings" class="progress-description text-white">
|
||||
전체 사이트 설정 변경 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-server mr-1"></i>
|
||||
시스템 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-caret-up"></i> 99.2%
|
||||
</span>
|
||||
<h5 class="description-header">서버 업타임</h5>
|
||||
<span class="description-text">지난 30일</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-caret-up"></i> 2.3초
|
||||
</span>
|
||||
<h5 class="description-header">평균 응답시간</h5>
|
||||
<span class="description-text">페이지 로딩</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 봇 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-check-circle"></i> 연결됨
|
||||
</span>
|
||||
<h5 class="description-header">봇 상태</h5>
|
||||
<span class="description-text">정상 작동</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-paper-plane"></i> 24개
|
||||
</span>
|
||||
<h5 class="description-header">전송된 알림</h5>
|
||||
<span class="description-text">오늘</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/admin/telegram" class="btn btn-success btn-sm">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
360
.history/views/admin/dashboard_20251026212607.ejs
Normal file
360
.history/views/admin/dashboard_20251026212607.ejs
Normal file
@@ -0,0 +1,360 @@
|
||||
|
||||
<!-- Dashboard Content -->
|
||||
<div class="row">
|
||||
<!-- Stats Cards -->
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info elevation-1">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">포트폴리오 프로젝트</span>
|
||||
<span class="info-box-number"><%= stats.portfolioCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-info" style="width: 70%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
70% 완료된 프로젝트
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-success elevation-1">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">제공 서비스</span>
|
||||
<span class="info-box-number"><%= stats.servicesCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 서비스 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-warning elevation-1">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">문의 메시지</span>
|
||||
<span class="info-box-number"><%= stats.contactsCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-warning" style="width: 60%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
60% 응답 완료
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-danger elevation-1">
|
||||
<i class="fas fa-users"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">관리자 계정</span>
|
||||
<span class="info-box-number"><%= stats.usersCount || 0 %></span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-danger" style="width: 100%"></div>
|
||||
</div>
|
||||
<span class="progress-description">
|
||||
모든 계정 활성화
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Row -->
|
||||
<div class="row">
|
||||
<!-- Recent Portfolio Projects -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-briefcase mr-1"></i>
|
||||
최근 포트폴리오 프로젝트
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentPortfolio && recentPortfolio.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentPortfolio.forEach(function(project, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentPortfolio.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-info badge-pill">
|
||||
<i class="fas fa-code"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= project.title %></h6>
|
||||
<p class="text-muted mb-1"><%= project.category %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-calendar mr-1"></i>
|
||||
<%= project.createdAt ? project.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= project.status === 'completed' ? 'success' : project.status === 'in-progress' ? 'warning' : 'secondary' %>">
|
||||
<%= project.status === 'completed' ? '완료' : project.status === 'in-progress' ? '진행중' : '계획' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/portfolio" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-eye mr-1"></i>
|
||||
모든 프로젝트 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-briefcase fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">아직 포트폴리오 프로젝트가 없습니다.</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
첫 번째 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Contact Messages -->
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-envelope mr-1"></i>
|
||||
최근 문의 메시지
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<% if (recentContacts && recentContacts.length > 0) { %>
|
||||
<ul class="list-unstyled">
|
||||
<% recentContacts.forEach(function(contact, index) { %>
|
||||
<li class="d-flex align-items-center <%= index < recentContacts.length - 1 ? 'border-bottom pb-3 mb-3' : '' %>">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<%= contact.name ? contact.name.charAt(0).toUpperCase() : 'U' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow-1 ml-3">
|
||||
<h6 class="mb-1 font-weight-bold"><%= contact.name %></h6>
|
||||
<p class="text-muted mb-1"><%= contact.email %></p>
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-clock mr-1"></i>
|
||||
<%= contact.createdAt ? contact.createdAt.toLocaleDateString('ko-KR') : '날짜 없음' %>
|
||||
</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<span class="badge badge-<%= contact.status === 'replied' ? 'success' : contact.status === 'pending' ? 'warning' : 'secondary' %>">
|
||||
<%= contact.status === 'replied' ? '답변완료' : contact.status === 'pending' ? '대기중' : '신규' %>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="/admin/contacts" class="btn btn-warning btn-sm">
|
||||
<i class="fas fa-envelope-open mr-1"></i>
|
||||
모든 문의 보기
|
||||
</a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-envelope fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">새로운 문의가 없습니다.</p>
|
||||
<small class="text-muted">고객 문의가 들어오면 여기에 표시됩니다.</small>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions & Tools -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-bolt mr-1"></i>
|
||||
빠른 작업
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-info">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">새 프로젝트</span>
|
||||
<span class="info-box-number">추가하기</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/portfolio/add" class="progress-description text-white">
|
||||
포트폴리오에 새 프로젝트 추가 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-success">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">서비스 관리</span>
|
||||
<span class="info-box-number">설정</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/services" class="progress-description text-white">
|
||||
서비스 가격 및 내용 수정 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-warning">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">미디어</span>
|
||||
<span class="info-box-number">업로드</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/media" class="progress-description text-white">
|
||||
이미지 및 파일 관리 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="info-box bg-gradient-danger">
|
||||
<span class="info-box-icon">
|
||||
<i class="fas fa-wrench"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">사이트 설정</span>
|
||||
<span class="info-box-number">관리</span>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: 100%"></div>
|
||||
</div>
|
||||
<a href="/admin/settings" class="progress-description text-white">
|
||||
전체 사이트 설정 변경 →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Status -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-server mr-1"></i>
|
||||
시스템 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-caret-up"></i> 99.2%
|
||||
</span>
|
||||
<h5 class="description-header">서버 업타임</h5>
|
||||
<span class="description-text">지난 30일</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-caret-up"></i> 2.3초
|
||||
</span>
|
||||
<h5 class="description-header">평균 응답시간</h5>
|
||||
<span class="description-text">페이지 로딩</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 봇 상태
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="description-block border-right">
|
||||
<span class="description-percentage text-success">
|
||||
<i class="fas fa-check-circle"></i> 연결됨
|
||||
</span>
|
||||
<h5 class="description-header">봇 상태</h5>
|
||||
<span class="description-text">정상 작동</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="description-block">
|
||||
<span class="description-percentage text-info">
|
||||
<i class="fas fa-paper-plane"></i> 24개
|
||||
</span>
|
||||
<h5 class="description-header">전송된 알림</h5>
|
||||
<span class="description-text">오늘</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/admin/telegram" class="btn btn-success btn-sm">
|
||||
<i class="fab fa-telegram mr-1"></i>
|
||||
텔레그램 설정
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
268
.history/views/admin/layout-adminlte_20251026211349.ejs
Normal file
268
.history/views/admin/layout-adminlte_20251026211349.ejs
Normal file
@@ -0,0 +1,268 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- AdminLTE CSS -->
|
||||
<link rel="stylesheet" href="/node_modules/admin-lte/dist/css/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<span class="badge badge-info right"><%= stats?.portfolioCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<span class="badge badge-success right"><%= stats?.servicesCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<span class="badge badge-warning right"><%= stats?.contactsCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- AdminLTE JavaScript -->
|
||||
<script src="/node_modules/admin-lte/plugins/jquery/jquery.min.js"></script>
|
||||
<script src="/node_modules/admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/node_modules/admin-lte/dist/js/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
268
.history/views/admin/layout-adminlte_20251026211450.ejs
Normal file
268
.history/views/admin/layout-adminlte_20251026211450.ejs
Normal file
@@ -0,0 +1,268 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- AdminLTE CSS -->
|
||||
<link rel="stylesheet" href="/node_modules/admin-lte/dist/css/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<span class="badge badge-info right"><%= stats?.portfolioCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<span class="badge badge-success right"><%= stats?.servicesCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<span class="badge badge-warning right"><%= stats?.contactsCount || 0 %></span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- AdminLTE JavaScript -->
|
||||
<script src="/node_modules/admin-lte/plugins/jquery/jquery.min.js"></script>
|
||||
<script src="/node_modules/admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/node_modules/admin-lte/dist/js/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
251
.history/views/admin/layout-tabler_20251026211559.ejs
Normal file
251
.history/views/admin/layout-tabler_20251026211559.ejs
Normal file
@@ -0,0 +1,251 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Tabler CSS -->
|
||||
<link href="/node_modules/@tabler/core/dist/css/tabler.min.css" rel="stylesheet"/>
|
||||
<link href="/node_modules/@tabler/icons/icons-sprite.svg" rel="stylesheet"/>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-weight: 700;
|
||||
color: #206bc4 !important;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
background: white !important;
|
||||
}
|
||||
|
||||
.navbar-nav .nav-link:hover {
|
||||
background-color: rgba(32, 107, 196, 0.1);
|
||||
}
|
||||
|
||||
.navbar-vertical .navbar-nav .nav-link {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.page-wrapper {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<!-- Sidebar -->
|
||||
<aside class="navbar navbar-vertical navbar-expand-lg" data-bs-theme="light">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu" aria-controls="sidebar-menu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<h1 class="navbar-brand navbar-brand-autodark">
|
||||
<a href="/admin/dashboard">
|
||||
<img src="/images/icons/icon-192x192.png" width="110" height="32" alt="SmartSolTech" class="navbar-brand-image">
|
||||
SmartSolTech
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<div class="collapse navbar-collapse" id="sidebar-menu">
|
||||
<ul class="navbar-nav pt-lg-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>" href="/admin/dashboard">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">대시보드</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#navbar-help" data-bs-toggle="dropdown" data-bs-auto-close="false" role="button" aria-expanded="false">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">포트폴리오</span>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/admin/portfolio">
|
||||
모든 프로젝트
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/portfolio/add">
|
||||
새 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'services' ? 'active' : '' %>" href="/admin/services">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">서비스 관리</span>
|
||||
<span class="badge badge-sm bg-green text-white ms-2"><%= stats?.servicesCount || 0 %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>" href="/admin/contacts">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">문의 관리</span>
|
||||
<span class="badge badge-sm bg-yellow text-white ms-2"><%= stats?.contactsCount || 0 %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'media' ? 'active' : '' %>" href="/admin/media">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">미디어 관리</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#navbar-settings" data-bs-toggle="dropdown" data-bs-auto-close="false" role="button" aria-expanded="false">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">시스템</span>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/admin/settings">
|
||||
사이트 설정
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/telegram">
|
||||
텔레그램 봇
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/banner-editor">
|
||||
배너 편집기
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="navbar navbar-expand-md d-print-none">
|
||||
<div class="container-xl">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu" aria-controls="navbar-menu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="navbar-nav flex-row order-md-last">
|
||||
<div class="nav-item dropdown">
|
||||
<a href="#" class="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown" aria-label="Open user menu">
|
||||
<span class="avatar avatar-sm" style="background-image: url('/images/icons/icon-192x192.png')"></span>
|
||||
<div class="d-none d-xl-block ps-2">
|
||||
<div><%= user ? user.name : '관리자' %></div>
|
||||
<div class="mt-1 small text-muted">관리자</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
||||
<a href="/admin/settings" class="dropdown-item">설정</a>
|
||||
<a href="/" target="_blank" class="dropdown-item">사이트 보기</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<!-- Page header -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="container-xl">
|
||||
<div class="row g-2 align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">
|
||||
<%= title %>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page body -->
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<%- body %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabler JavaScript -->
|
||||
<script src="/node_modules/@tabler/core/dist/js/tabler.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization and enhancements
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add smooth transitions for navigation
|
||||
const navLinks = document.querySelectorAll('.nav-link');
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener('click', function() {
|
||||
if (!this.classList.contains('active') && !this.classList.contains('dropdown-toggle')) {
|
||||
const currentActive = document.querySelector('.nav-link.active');
|
||||
if (currentActive) {
|
||||
currentActive.classList.remove('active');
|
||||
}
|
||||
this.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
251
.history/views/admin/layout-tabler_20251026211716.ejs
Normal file
251
.history/views/admin/layout-tabler_20251026211716.ejs
Normal file
@@ -0,0 +1,251 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Tabler CSS -->
|
||||
<link href="/node_modules/@tabler/core/dist/css/tabler.min.css" rel="stylesheet"/>
|
||||
<link href="/node_modules/@tabler/icons/icons-sprite.svg" rel="stylesheet"/>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-weight: 700;
|
||||
color: #206bc4 !important;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
background: white !important;
|
||||
}
|
||||
|
||||
.navbar-nav .nav-link:hover {
|
||||
background-color: rgba(32, 107, 196, 0.1);
|
||||
}
|
||||
|
||||
.navbar-vertical .navbar-nav .nav-link {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.page-wrapper {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<!-- Sidebar -->
|
||||
<aside class="navbar navbar-vertical navbar-expand-lg" data-bs-theme="light">
|
||||
<div class="container-fluid">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu" aria-controls="sidebar-menu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<h1 class="navbar-brand navbar-brand-autodark">
|
||||
<a href="/admin/dashboard">
|
||||
<img src="/images/icons/icon-192x192.png" width="110" height="32" alt="SmartSolTech" class="navbar-brand-image">
|
||||
SmartSolTech
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<div class="collapse navbar-collapse" id="sidebar-menu">
|
||||
<ul class="navbar-nav pt-lg-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>" href="/admin/dashboard">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">대시보드</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#navbar-help" data-bs-toggle="dropdown" data-bs-auto-close="false" role="button" aria-expanded="false">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-briefcase"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">포트폴리오</span>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/admin/portfolio">
|
||||
모든 프로젝트
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/portfolio/add">
|
||||
새 프로젝트 추가
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'services' ? 'active' : '' %>" href="/admin/services">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">서비스 관리</span>
|
||||
<span class="badge badge-sm bg-green text-white ms-2"><%= stats?.servicesCount || 0 %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>" href="/admin/contacts">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-envelope"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">문의 관리</span>
|
||||
<span class="badge badge-sm bg-yellow text-white ms-2"><%= stats?.contactsCount || 0 %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <%= currentPage === 'media' ? 'active' : '' %>" href="/admin/media">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-images"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">미디어 관리</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#navbar-settings" data-bs-toggle="dropdown" data-bs-auto-close="false" role="button" aria-expanded="false">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
<span class="nav-link-title">시스템</span>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/admin/settings">
|
||||
사이트 설정
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/telegram">
|
||||
텔레그램 봇
|
||||
</a>
|
||||
<a class="dropdown-item" href="/admin/banner-editor">
|
||||
배너 편집기
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="navbar navbar-expand-md d-print-none">
|
||||
<div class="container-xl">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu" aria-controls="navbar-menu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="navbar-nav flex-row order-md-last">
|
||||
<div class="nav-item dropdown">
|
||||
<a href="#" class="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown" aria-label="Open user menu">
|
||||
<span class="avatar avatar-sm" style="background-image: url('/images/icons/icon-192x192.png')"></span>
|
||||
<div class="d-none d-xl-block ps-2">
|
||||
<div><%= user ? user.name : '관리자' %></div>
|
||||
<div class="mt-1 small text-muted">관리자</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
||||
<a href="/admin/settings" class="dropdown-item">설정</a>
|
||||
<a href="/" target="_blank" class="dropdown-item">사이트 보기</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<!-- Page header -->
|
||||
<div class="page-header d-print-none">
|
||||
<div class="container-xl">
|
||||
<div class="row g-2 align-items-center">
|
||||
<div class="col">
|
||||
<h2 class="page-title">
|
||||
<%= title %>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page body -->
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<%- body %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabler JavaScript -->
|
||||
<script src="/node_modules/@tabler/core/dist/js/tabler.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization and enhancements
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add smooth transitions for navigation
|
||||
const navLinks = document.querySelectorAll('.nav-link');
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener('click', function() {
|
||||
if (!this.classList.contains('active') && !this.classList.contains('dropdown-toggle')) {
|
||||
const currentActive = document.querySelector('.nav-link.active');
|
||||
if (currentActive) {
|
||||
currentActive.classList.remove('active');
|
||||
}
|
||||
this.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
276
.history/views/admin/layout_20251026212417.ejs
Normal file
276
.history/views/admin/layout_20251026212417.ejs
Normal file
@@ -0,0 +1,276 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- AdminLTE CSS -->
|
||||
<link rel="stylesheet" href="/node_modules/admin-lte/dist/css/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="/node_modules/admin-lte/dist/js/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
276
.history/views/admin/layout_20251026212427.ejs
Normal file
276
.history/views/admin/layout_20251026212427.ejs
Normal file
@@ -0,0 +1,276 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- AdminLTE CSS -->
|
||||
<link rel="stylesheet" href="/node_modules/admin-lte/dist/css/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="/node_modules/admin-lte/dist/js/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
279
.history/views/admin/layout_20251026215820.ejs
Normal file
279
.history/views/admin/layout_20251026215820.ejs
Normal file
@@ -0,0 +1,279 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="/node_modules/admin-lte/dist/js/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
279
.history/views/admin/layout_20251026215830.ejs
Normal file
279
.history/views/admin/layout_20251026215830.ejs
Normal file
@@ -0,0 +1,279 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery (Local) -->
|
||||
<script src="/vendor/jquery/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 (Local) -->
|
||||
<script src="/vendor/bootstrap/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App (Local) -->
|
||||
<script src="/vendor/adminlte/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
279
.history/views/admin/layout_20251026215850.ejs
Normal file
279
.history/views/admin/layout_20251026215850.ejs
Normal file
@@ -0,0 +1,279 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery (Local) -->
|
||||
<script src="/vendor/jquery/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 (Local) -->
|
||||
<script src="/vendor/bootstrap/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App (Local) -->
|
||||
<script src="/vendor/adminlte/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
328
.history/views/admin/layout_20251026220236.ejs
Normal file
328
.history/views/admin/layout_20251026220236.ejs
Normal file
@@ -0,0 +1,328 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
/* Sidebar navigation styles */
|
||||
.main-sidebar .nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 8px;
|
||||
transition: all 0.3s ease;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link:hover {
|
||||
background-color: rgba(0, 123, 255, 0.1);
|
||||
color: #007bff;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||
color: white !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active i {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active .badge {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Fix for navigation icons */
|
||||
.nav-icon {
|
||||
margin-right: 8px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
/* Breadcrumb styling */
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.breadcrumb-item a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.breadcrumb-item.active {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Content wrapper padding */
|
||||
.content-wrapper {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
/* Badges in navigation */
|
||||
.nav-sidebar .badge {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery (Local) -->
|
||||
<script src="/vendor/jquery/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 (Local) -->
|
||||
<script src="/vendor/bootstrap/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App (Local) -->
|
||||
<script src="/vendor/adminlte/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
353
.history/views/admin/layout_20251026220250.ejs
Normal file
353
.history/views/admin/layout_20251026220250.ejs
Normal file
@@ -0,0 +1,353 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
/* Sidebar navigation styles */
|
||||
.main-sidebar .nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 8px;
|
||||
transition: all 0.3s ease;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link:hover {
|
||||
background-color: rgba(0, 123, 255, 0.1);
|
||||
color: #007bff;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||
color: white !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active i {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active .badge {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Fix for navigation icons */
|
||||
.nav-icon {
|
||||
margin-right: 8px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
/* Breadcrumb styling */
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.breadcrumb-item a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.breadcrumb-item.active {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Content wrapper padding */
|
||||
.content-wrapper {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
/* Badges in navigation */
|
||||
.nav-sidebar .badge {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery (Local) -->
|
||||
<script src="/vendor/jquery/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 (Local) -->
|
||||
<script src="/vendor/bootstrap/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App (Local) -->
|
||||
<script src="/vendor/adminlte/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Get current page from URL
|
||||
const currentPath = window.location.pathname;
|
||||
const currentPage = currentPath.split('/').pop() || 'dashboard';
|
||||
|
||||
// Remove active class from all nav links
|
||||
$('.nav-sidebar .nav-link').removeClass('active');
|
||||
|
||||
// Add active class to current page nav link
|
||||
$('.nav-sidebar .nav-link').each(function() {
|
||||
const href = $(this).attr('href');
|
||||
if (href) {
|
||||
const pageName = href.split('/').pop();
|
||||
if (currentPath.includes(pageName) ||
|
||||
(currentPath === '/admin' && pageName === 'dashboard') ||
|
||||
(currentPath === '/admin/' && pageName === 'dashboard')) {
|
||||
$(this).addClass('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize AdminLTE components
|
||||
if (typeof AdminLTE !== 'undefined') {
|
||||
AdminLTE.init();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
353
.history/views/admin/layout_20251026220452.ejs
Normal file
353
.history/views/admin/layout_20251026220452.ejs
Normal file
@@ -0,0 +1,353 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= currentLanguage %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %> - SmartSolTech Admin</title>
|
||||
|
||||
<!-- Bootstrap CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/bootstrap/bootstrap.min.css">
|
||||
|
||||
<!-- AdminLTE CSS (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/adminlte.min.css">
|
||||
|
||||
<!-- Font Awesome (Local) -->
|
||||
<link rel="stylesheet" href="/vendor/adminlte/fontawesome.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom Korean Admin Styles -->
|
||||
<style>
|
||||
body, .content-wrapper, .main-sidebar {
|
||||
font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
font-weight: 700;
|
||||
color: #007bff !important;
|
||||
}
|
||||
|
||||
/* Sidebar navigation styles */
|
||||
.main-sidebar .nav-sidebar .nav-link {
|
||||
border-radius: 8px;
|
||||
margin: 2px 8px;
|
||||
transition: all 0.3s ease;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link:hover {
|
||||
background-color: rgba(0, 123, 255, 0.1);
|
||||
color: #007bff;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||
color: white !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3);
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active i {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.main-sidebar .nav-sidebar .nav-link.active .badge {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Fix for navigation icons */
|
||||
.nav-icon {
|
||||
margin-right: 8px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-box-icon {
|
||||
border-radius: 12px 0 0 12px;
|
||||
}
|
||||
|
||||
.navbar-light {
|
||||
background: white !important;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.main-sidebar {
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
/* Breadcrumb styling */
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.breadcrumb-item a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.breadcrumb-item.active {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Content wrapper padding */
|
||||
.content-wrapper {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
/* Badges in navigation */
|
||||
.nav-sidebar .badge {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="hold-transition sidebar-mini layout-fixed">
|
||||
<div class="wrapper">
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand navbar-light">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="/" class="nav-link" target="_blank">
|
||||
<i class="fas fa-external-link-alt mr-1"></i>
|
||||
사이트 보기
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- User Menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="far fa-user mr-1"></i>
|
||||
<%= user ? user.name : '관리자' %>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="/admin/settings" class="dropdown-item">
|
||||
<i class="fas fa-cog mr-2"></i> 설정
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="/admin/logout" method="post" class="dropdown-item p-0">
|
||||
<button type="submit" class="btn btn-link text-left w-100 text-danger">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> 로그아웃
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-light-primary elevation-4">
|
||||
<!-- Brand Logo -->
|
||||
<a href="/admin/dashboard" class="brand-link">
|
||||
<img src="/images/icons/icon-192x192.png" alt="SmartSolTech" class="brand-image img-circle elevation-3" style="opacity: .8">
|
||||
<span class="brand-text font-weight-bold">SmartSolTech</span>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<!-- Sidebar Menu -->
|
||||
<nav class="mt-3">
|
||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||
<li class="nav-item">
|
||||
<a href="/admin/dashboard" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>대시보드</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/portfolio" class="nav-link <%= currentPage === 'portfolio' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-briefcase"></i>
|
||||
<p>
|
||||
포트폴리오
|
||||
<% if (typeof stats !== 'undefined' && stats.portfolioCount) { %>
|
||||
<span class="badge badge-info right"><%= stats.portfolioCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/services" class="nav-link <%= currentPage === 'services' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>
|
||||
서비스 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.servicesCount) { %>
|
||||
<span class="badge badge-success right"><%= stats.servicesCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/contacts" class="nav-link <%= currentPage === 'contacts' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-envelope"></i>
|
||||
<p>
|
||||
문의 관리
|
||||
<% if (typeof stats !== 'undefined' && stats.contactsCount) { %>
|
||||
<span class="badge badge-warning right"><%= stats.contactsCount %></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/media" class="nav-link <%= currentPage === 'media' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-images"></i>
|
||||
<p>미디어 관리</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-header">시스템 설정</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/settings" class="nav-link <%= currentPage === 'settings' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-cog"></i>
|
||||
<p>사이트 설정</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/telegram" class="nav-link <%= currentPage === 'telegram' ? 'active' : '' %>">
|
||||
<i class="nav-icon fab fa-telegram"></i>
|
||||
<p>텔레그램 봇</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="/admin/banner-editor" class="nav-link <%= currentPage === 'banner-editor' ? 'active' : '' %>">
|
||||
<i class="nav-icon fas fa-paint-brush"></i>
|
||||
<p>배너 편집기</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Wrapper -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="m-0"><%= title %></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">홈</a></li>
|
||||
<% if (currentPage !== 'dashboard') { %>
|
||||
<li class="breadcrumb-item active"><%= title %></li>
|
||||
<% } %>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<%- body %>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="main-footer">
|
||||
<strong>© 2024 <a href="/">SmartSolTech</a></strong>
|
||||
모든 권리 보유.
|
||||
<div class="float-right d-none d-sm-inline-block">
|
||||
<b>Version</b> 2.0.0
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- jQuery (Local) -->
|
||||
<script src="/vendor/jquery/jquery-3.6.0.min.js"></script>
|
||||
<!-- Bootstrap 4 (Local) -->
|
||||
<script src="/vendor/bootstrap/bootstrap.bundle.min.js"></script>
|
||||
<!-- AdminLTE App (Local) -->
|
||||
<script src="/vendor/adminlte/adminlte.min.js"></script>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
// Korean localization for AdminLTE
|
||||
$(document).ready(function() {
|
||||
// Update any English text to Korean
|
||||
$('.brand-link .brand-text').text('스마트솔테크');
|
||||
|
||||
// Get current page from URL
|
||||
const currentPath = window.location.pathname;
|
||||
const currentPage = currentPath.split('/').pop() || 'dashboard';
|
||||
|
||||
// Remove active class from all nav links
|
||||
$('.nav-sidebar .nav-link').removeClass('active');
|
||||
|
||||
// Add active class to current page nav link
|
||||
$('.nav-sidebar .nav-link').each(function() {
|
||||
const href = $(this).attr('href');
|
||||
if (href) {
|
||||
const pageName = href.split('/').pop();
|
||||
if (currentPath.includes(pageName) ||
|
||||
(currentPath === '/admin' && pageName === 'dashboard') ||
|
||||
(currentPath === '/admin/' && pageName === 'dashboard')) {
|
||||
$(this).addClass('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add smooth transitions
|
||||
$('.nav-link').on('click', function() {
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.nav-link.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize AdminLTE components
|
||||
if (typeof AdminLTE !== 'undefined') {
|
||||
AdminLTE.init();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
788
.history/views/admin/media_20251026214204.ejs
Normal file
788
.history/views/admin/media_20251026214204.ejs
Normal file
@@ -0,0 +1,788 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-images mr-2"></i>Медиа Галерея</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="float-sm-right">
|
||||
<button id="refresh-btn" class="btn btn-secondary">
|
||||
<i class="fas fa-sync-alt mr-1"></i>Обновить
|
||||
</button>
|
||||
<button id="upload-btn" class="btn btn-primary">
|
||||
<i class="fas fa-upload mr-1"></i>Загрузить файлы
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Upload Zone -->
|
||||
<div id="upload-zone" class="card" style="display: none;">
|
||||
<div class="card-body text-center">
|
||||
<div class="mb-4">
|
||||
<i class="fas fa-cloud-upload-alt fa-6x text-muted mb-4"></i>
|
||||
<p class="h5 text-muted mb-2">Перетащите файлы сюда или нажмите для выбора</p>
|
||||
<p class="text-muted">Поддерживаются: JPG, PNG, GIF, SVG (максимум 10MB каждый)</p>
|
||||
</div>
|
||||
<input type="file" id="file-input" multiple accept="image/*" class="d-none">
|
||||
<button type="button" onclick="document.getElementById('file-input').click()" class="btn btn-primary">
|
||||
Выбрать файлы
|
||||
</button>
|
||||
<button id="cancel-upload" class="btn btn-secondary ml-3">
|
||||
Отмена
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Upload Progress -->
|
||||
<div id="upload-progress" class="card" style="display: none;">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Загрузка файлов</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="progress-list">
|
||||
<!-- Progress items will be added here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter and Search -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Тип файла</label>
|
||||
<select id="file-type-filter" class="form-control">
|
||||
<option value="">Все типы</option>
|
||||
<option value="image/jpeg">JPEG</option>
|
||||
<option value="image/png">PNG</option>
|
||||
<option value="image/gif">GIF</option>
|
||||
<option value="image/svg+xml">SVG</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Размер</label>
|
||||
<select id="size-filter" class="form-control">
|
||||
<option value="">Любой размер</option>
|
||||
<option value="small">Маленький (< 1MB)</option>
|
||||
<option value="medium">Средний (1-5MB)</option>
|
||||
<option value="large">Большой (> 5MB)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label>Поиск</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="search-input" placeholder="Поиск по имени файла..." class="form-control">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Media Grid -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Файлы</h3>
|
||||
<div class="card-tools">
|
||||
<span id="file-count" class="badge badge-secondary">Загрузка...</span>
|
||||
<div class="btn-group ml-2">
|
||||
<button id="grid-view" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-th-large"></i>
|
||||
</button>
|
||||
<button id="list-view" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-list"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Loading State -->
|
||||
<div id="loading" class="text-center py-5">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Загрузка...</span>
|
||||
</div>
|
||||
<p class="mt-2 text-muted">Загрузка медиа файлов...</p>
|
||||
</div>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div id="empty-state" class="text-center py-5" style="display: none;">
|
||||
<i class="fas fa-images fa-6x text-muted mb-4"></i>
|
||||
<h4 class="text-muted mb-2">Нет загруженных файлов</h4>
|
||||
<p class="text-muted mb-4">Начните с загрузки ваших первых изображений</p>
|
||||
<button onclick="document.getElementById('upload-btn').click()" class="btn btn-primary">
|
||||
<i class="fas fa-upload mr-2"></i>Загрузить файлы
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Media Grid -->
|
||||
<div id="media-grid" class="row">
|
||||
<!-- Media items will be loaded here -->
|
||||
</div>
|
||||
|
||||
<!-- Media List -->
|
||||
<div id="media-list" style="display: none;">
|
||||
<!-- List items will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="card-footer" id="pagination" style="display: none;">
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center m-0">
|
||||
<li class="page-item">
|
||||
<button id="prev-page" class="page-link">
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</button>
|
||||
</li>
|
||||
<div id="page-numbers" class="d-flex">
|
||||
<!-- Page numbers will be added here -->
|
||||
</div>
|
||||
<li class="page-item">
|
||||
<button id="next-page" class="page-link">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Media Preview Modal -->
|
||||
<div class="modal fade" id="preview-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 id="modal-title" class="modal-title">Предпросмотр файла</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<img id="modal-image" src="" alt="" class="img-fluid rounded">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label>Имя файла</label>
|
||||
<input id="modal-filename" type="text" class="form-control" readonly>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>URL</label>
|
||||
<div class="input-group">
|
||||
<input id="modal-url" type="text" class="form-control" readonly>
|
||||
<div class="input-group-append">
|
||||
<button onclick="copyToClipboard()" class="btn btn-outline-secondary" type="button">
|
||||
<i class="fas fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Размер</label>
|
||||
<p id="modal-size" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Тип</label>
|
||||
<p id="modal-type" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Ширина</label>
|
||||
<p id="modal-width" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Высота</label>
|
||||
<p id="modal-height" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Загружено</label>
|
||||
<p id="modal-date" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="btn-group d-flex">
|
||||
<button onclick="downloadFile()" class="btn btn-primary">
|
||||
<i class="fas fa-download mr-1"></i>Скачать
|
||||
</button>
|
||||
<button onclick="deleteFile()" class="btn btn-danger">
|
||||
<i class="fas fa-trash mr-1"></i>Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
class MediaGallery {
|
||||
constructor() {
|
||||
this.currentFiles = [];
|
||||
this.filteredFiles = [];
|
||||
this.currentView = 'grid';
|
||||
this.currentPage = 1;
|
||||
this.itemsPerPage = 24;
|
||||
this.currentFile = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupEventListeners();
|
||||
this.loadMedia();
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Upload button
|
||||
document.getElementById('upload-btn').addEventListener('click', () => {
|
||||
this.showUploadZone();
|
||||
});
|
||||
|
||||
// Cancel upload
|
||||
document.getElementById('cancel-upload').addEventListener('click', () => {
|
||||
this.hideUploadZone();
|
||||
});
|
||||
|
||||
// File input
|
||||
document.getElementById('file-input').addEventListener('change', (e) => {
|
||||
this.handleFiles(e.target.files);
|
||||
});
|
||||
|
||||
// Refresh button
|
||||
document.getElementById('refresh-btn').addEventListener('click', () => {
|
||||
this.loadMedia();
|
||||
});
|
||||
|
||||
// View toggle
|
||||
document.getElementById('grid-view').addEventListener('click', () => {
|
||||
this.setView('grid');
|
||||
});
|
||||
|
||||
document.getElementById('list-view').addEventListener('click', () => {
|
||||
this.setView('list');
|
||||
});
|
||||
|
||||
// Filters
|
||||
document.getElementById('file-type-filter').addEventListener('change', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
document.getElementById('size-filter').addEventListener('change', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
document.getElementById('search-input').addEventListener('input', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
// Modal
|
||||
document.getElementById('close-modal').addEventListener('click', () => {
|
||||
this.closeModal();
|
||||
});
|
||||
|
||||
// Upload zone drag and drop
|
||||
const uploadZone = document.getElementById('upload-zone');
|
||||
uploadZone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
uploadZone.classList.add('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
uploadZone.addEventListener('dragleave', () => {
|
||||
uploadZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
uploadZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
uploadZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
this.handleFiles(e.dataTransfer.files);
|
||||
});
|
||||
}
|
||||
|
||||
async loadMedia() {
|
||||
try {
|
||||
document.getElementById('loading').style.display = 'block';
|
||||
document.getElementById('empty-state').style.display = 'none';
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
|
||||
const response = await fetch('/api/media/list');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.currentFiles = data.images || [];
|
||||
this.applyFilters();
|
||||
} else {
|
||||
throw new Error(data.message || 'Failed to load media');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading media:', error);
|
||||
this.showError('Ошибка загрузки медиа файлов');
|
||||
} finally {
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
const typeFilter = document.getElementById('file-type-filter').value;
|
||||
const sizeFilter = document.getElementById('size-filter').value;
|
||||
const searchQuery = document.getElementById('search-input').value.toLowerCase();
|
||||
|
||||
this.filteredFiles = this.currentFiles.filter(file => {
|
||||
// Type filter
|
||||
if (typeFilter && file.mimetype !== typeFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Size filter
|
||||
if (sizeFilter) {
|
||||
const sizeInMB = file.size / (1024 * 1024);
|
||||
if (sizeFilter === 'small' && sizeInMB >= 1) return false;
|
||||
if (sizeFilter === 'medium' && (sizeInMB < 1 || sizeInMB > 5)) return false;
|
||||
if (sizeFilter === 'large' && sizeInMB <= 5) return false;
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if (searchQuery && !file.filename.toLowerCase().includes(searchQuery)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.updateFileCount();
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
updateFileCount() {
|
||||
const total = this.currentFiles.length;
|
||||
const filtered = this.filteredFiles.length;
|
||||
const countText = filtered === total ?
|
||||
`${total} файлов` :
|
||||
`${filtered} из ${total} файлов`;
|
||||
|
||||
document.getElementById('file-count').textContent = countText;
|
||||
}
|
||||
|
||||
renderMedia() {
|
||||
if (this.filteredFiles.length === 0) {
|
||||
document.getElementById('empty-state').style.display = 'block';
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
document.getElementById('media-list').style.display = 'none';
|
||||
document.getElementById('pagination').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('empty-state').style.display = 'none';
|
||||
|
||||
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
|
||||
const endIndex = startIndex + this.itemsPerPage;
|
||||
const pageFiles = this.filteredFiles.slice(startIndex, endIndex);
|
||||
|
||||
if (this.currentView === 'grid') {
|
||||
this.renderGrid(pageFiles);
|
||||
} else {
|
||||
this.renderList(pageFiles);
|
||||
}
|
||||
|
||||
this.updatePagination();
|
||||
}
|
||||
|
||||
renderGrid(files) {
|
||||
document.getElementById('media-grid').style.display = 'grid';
|
||||
document.getElementById('media-list').style.display = 'none';
|
||||
|
||||
const grid = document.getElementById('media-grid');
|
||||
grid.innerHTML = files.map(file => `
|
||||
<div class="group relative bg-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow"
|
||||
onclick="mediaGallery.openModal('${file.filename}')">
|
||||
<div class="aspect-square">
|
||||
<img src="${file.url}" alt="${file.filename}"
|
||||
class="w-full h-full object-cover">
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-25 transition-opacity flex items-center justify-center">
|
||||
<div class="opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<button class="bg-white bg-opacity-90 text-gray-800 px-3 py-2 rounded-lg mr-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.downloadFile('${file.filename}')">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
<button class="bg-red-500 bg-opacity-90 text-white px-3 py-2 rounded-lg"
|
||||
onclick="event.stopPropagation(); mediaGallery.deleteFile('${file.filename}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-75 text-white p-2">
|
||||
<p class="text-xs truncate">${file.filename}</p>
|
||||
<p class="text-xs text-gray-300">${this.formatFileSize(file.size)}</p>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
renderList(files) {
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
document.getElementById('media-list').style.display = 'block';
|
||||
|
||||
const list = document.getElementById('media-list');
|
||||
list.innerHTML = files.map(file => `
|
||||
<div class="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 cursor-pointer"
|
||||
onclick="mediaGallery.openModal('${file.filename}')">
|
||||
<div class="w-16 h-16 flex-shrink-0 mr-4">
|
||||
<img src="${file.url}" alt="${file.filename}"
|
||||
class="w-full h-full object-cover rounded">
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h4 class="text-sm font-medium text-gray-900 truncate">${file.filename}</h4>
|
||||
<p class="text-sm text-gray-500">${this.formatFileSize(file.size)} • ${file.mimetype}</p>
|
||||
<p class="text-xs text-gray-400">${new Date(file.uploadedAt).toLocaleDateString('ru-RU')}</p>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<button class="text-blue-600 hover:text-blue-800 p-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.downloadFile('${file.filename}')">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
<button class="text-red-600 hover:text-red-800 p-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.deleteFile('${file.filename}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
setView(view) {
|
||||
this.currentView = view;
|
||||
|
||||
// Update button states
|
||||
document.getElementById('grid-view').classList.toggle('bg-blue-600', view === 'grid');
|
||||
document.getElementById('grid-view').classList.toggle('text-white', view === 'grid');
|
||||
document.getElementById('list-view').classList.toggle('bg-blue-600', view === 'list');
|
||||
document.getElementById('list-view').classList.toggle('text-white', view === 'list');
|
||||
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
showUploadZone() {
|
||||
document.getElementById('upload-zone').style.display = 'block';
|
||||
}
|
||||
|
||||
hideUploadZone() {
|
||||
document.getElementById('upload-zone').style.display = 'none';
|
||||
document.getElementById('file-input').value = '';
|
||||
}
|
||||
|
||||
async handleFiles(files) {
|
||||
const validFiles = Array.from(files).filter(file => {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
this.showError(`${file.name} не является изображением`);
|
||||
return false;
|
||||
}
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
this.showError(`${file.name} слишком большой (максимум 10MB)`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (validFiles.length === 0) return;
|
||||
|
||||
this.hideUploadZone();
|
||||
await this.uploadFiles(validFiles);
|
||||
}
|
||||
|
||||
async uploadFiles(files) {
|
||||
const progressContainer = document.getElementById('upload-progress');
|
||||
const progressList = document.getElementById('progress-list');
|
||||
|
||||
progressContainer.style.display = 'block';
|
||||
progressList.innerHTML = '';
|
||||
|
||||
for (const file of files) {
|
||||
const progressItem = this.createProgressItem(file);
|
||||
progressList.appendChild(progressItem);
|
||||
|
||||
try {
|
||||
await this.uploadSingleFile(file, progressItem);
|
||||
} catch (error) {
|
||||
this.updateProgressItem(progressItem, 'error', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
progressContainer.style.display = 'none';
|
||||
this.loadMedia();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
createProgressItem(file) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'flex items-center justify-between p-3 bg-gray-50 rounded';
|
||||
div.innerHTML = `
|
||||
<div class="flex items-center space-x-3">
|
||||
<i class="fas fa-image text-gray-400"></i>
|
||||
<span class="text-sm text-gray-900">${file.name}</span>
|
||||
<span class="text-xs text-gray-500">${this.formatFileSize(file.size)}</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-32 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-blue-600 h-2 rounded-full progress-bar" style="width: 0%"></div>
|
||||
</div>
|
||||
<span class="text-sm text-gray-600 status">0%</span>
|
||||
</div>
|
||||
`;
|
||||
return div;
|
||||
}
|
||||
|
||||
updateProgressItem(item, status, message = '') {
|
||||
const statusElement = item.querySelector('.status');
|
||||
const progressBar = item.querySelector('.progress-bar');
|
||||
|
||||
if (status === 'error') {
|
||||
statusElement.textContent = 'Ошибка';
|
||||
statusElement.className = 'text-sm text-red-600 status';
|
||||
progressBar.className = 'bg-red-600 h-2 rounded-full progress-bar';
|
||||
progressBar.style.width = '100%';
|
||||
} else if (status === 'success') {
|
||||
statusElement.textContent = 'Готово';
|
||||
statusElement.className = 'text-sm text-green-600 status';
|
||||
progressBar.className = 'bg-green-600 h-2 rounded-full progress-bar';
|
||||
progressBar.style.width = '100%';
|
||||
}
|
||||
}
|
||||
|
||||
async uploadSingleFile(file, progressItem) {
|
||||
const formData = new FormData();
|
||||
formData.append('images', file);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
const progressBar = progressItem.querySelector('.progress-bar');
|
||||
const status = progressItem.querySelector('.status');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
xhr.upload.addEventListener('progress', (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = (e.loaded / e.total) * 100;
|
||||
progressBar.style.width = percentComplete + '%';
|
||||
status.textContent = Math.round(percentComplete) + '%';
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status === 200) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
if (response.success) {
|
||||
this.updateProgressItem(progressItem, 'success');
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(response.message));
|
||||
}
|
||||
} else {
|
||||
reject(new Error('Upload failed'));
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
reject(new Error('Network error'));
|
||||
});
|
||||
|
||||
xhr.open('POST', '/api/media/upload-multiple');
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
openModal(filename) {
|
||||
const file = this.currentFiles.find(f => f.filename === filename);
|
||||
if (!file) return;
|
||||
|
||||
this.currentFile = file;
|
||||
|
||||
document.getElementById('modal-title').textContent = file.filename;
|
||||
document.getElementById('modal-image').src = file.url;
|
||||
document.getElementById('modal-filename').value = file.filename;
|
||||
document.getElementById('modal-url').value = window.location.origin + file.url;
|
||||
document.getElementById('modal-size').textContent = this.formatFileSize(file.size);
|
||||
document.getElementById('modal-type').textContent = file.mimetype;
|
||||
document.getElementById('modal-date').textContent = new Date(file.uploadedAt).toLocaleDateString('ru-RU');
|
||||
|
||||
// Load image to get dimensions
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
document.getElementById('modal-width').textContent = img.width + 'px';
|
||||
document.getElementById('modal-height').textContent = img.height + 'px';
|
||||
};
|
||||
img.src = file.url;
|
||||
|
||||
document.getElementById('preview-modal').style.display = 'flex';
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
document.getElementById('preview-modal').style.display = 'none';
|
||||
this.currentFile = null;
|
||||
}
|
||||
|
||||
async deleteFile(filename) {
|
||||
if (!confirm(`Вы уверены, что хотите удалить файл "${filename}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/media/${filename}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
this.showSuccess('Файл удален');
|
||||
this.loadMedia();
|
||||
if (this.currentFile && this.currentFile.filename === filename) {
|
||||
this.closeModal();
|
||||
}
|
||||
} else {
|
||||
throw new Error('Failed to delete file');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting file:', error);
|
||||
this.showError('Ошибка удаления файла');
|
||||
}
|
||||
}
|
||||
|
||||
downloadFile(filename) {
|
||||
const file = filename ?
|
||||
this.currentFiles.find(f => f.filename === filename) :
|
||||
this.currentFile;
|
||||
|
||||
if (!file) return;
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = file.url;
|
||||
link.download = file.filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
updatePagination() {
|
||||
const totalPages = Math.ceil(this.filteredFiles.length / this.itemsPerPage);
|
||||
|
||||
if (totalPages <= 1) {
|
||||
document.getElementById('pagination').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('pagination').style.display = 'block';
|
||||
|
||||
// Update prev/next buttons
|
||||
document.getElementById('prev-page').disabled = this.currentPage === 1;
|
||||
document.getElementById('next-page').disabled = this.currentPage === totalPages;
|
||||
|
||||
// Update page numbers
|
||||
const pageNumbers = document.getElementById('page-numbers');
|
||||
pageNumbers.innerHTML = '';
|
||||
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
if (i === 1 || i === totalPages || (i >= this.currentPage - 2 && i <= this.currentPage + 2)) {
|
||||
const button = document.createElement('button');
|
||||
button.className = `px-3 py-2 rounded ${
|
||||
i === this.currentPage ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-600 hover:bg-gray-300'
|
||||
}`;
|
||||
button.textContent = i;
|
||||
button.onclick = () => this.goToPage(i);
|
||||
pageNumbers.appendChild(button);
|
||||
} else if (i === this.currentPage - 3 || i === this.currentPage + 3) {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'px-2 py-2 text-gray-400';
|
||||
span.textContent = '...';
|
||||
pageNumbers.appendChild(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goToPage(page) {
|
||||
this.currentPage = page;
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
this.showNotification(message, 'error');
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this.showNotification(message, 'success');
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `fixed top-4 right-4 px-6 py-3 rounded-lg text-white z-50 ${
|
||||
type === 'success' ? 'bg-green-500' :
|
||||
type === 'error' ? 'bg-red-500' : 'bg-blue-500'
|
||||
}`;
|
||||
notification.textContent = message;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.remove();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// Global functions for modal
|
||||
function copyToClipboard() {
|
||||
const urlInput = document.getElementById('modal-url');
|
||||
urlInput.select();
|
||||
document.execCommand('copy');
|
||||
mediaGallery.showSuccess('URL скопирован в буфер обмена');
|
||||
}
|
||||
|
||||
function downloadFile() {
|
||||
mediaGallery.downloadFile();
|
||||
}
|
||||
|
||||
function deleteFile() {
|
||||
if (mediaGallery.currentFile) {
|
||||
mediaGallery.deleteFile(mediaGallery.currentFile.filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
let mediaGallery;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
mediaGallery = new MediaGallery();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
788
.history/views/admin/media_20251026214214.ejs
Normal file
788
.history/views/admin/media_20251026214214.ejs
Normal file
@@ -0,0 +1,788 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-images mr-2"></i>Медиа Галерея</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="float-sm-right">
|
||||
<button id="refresh-btn" class="btn btn-secondary">
|
||||
<i class="fas fa-sync-alt mr-1"></i>Обновить
|
||||
</button>
|
||||
<button id="upload-btn" class="btn btn-primary">
|
||||
<i class="fas fa-upload mr-1"></i>Загрузить файлы
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Upload Zone -->
|
||||
<div id="upload-zone" class="card" style="display: none;">
|
||||
<div class="card-body text-center">
|
||||
<div class="mb-4">
|
||||
<i class="fas fa-cloud-upload-alt fa-6x text-muted mb-4"></i>
|
||||
<p class="h5 text-muted mb-2">Перетащите файлы сюда или нажмите для выбора</p>
|
||||
<p class="text-muted">Поддерживаются: JPG, PNG, GIF, SVG (максимум 10MB каждый)</p>
|
||||
</div>
|
||||
<input type="file" id="file-input" multiple accept="image/*" class="d-none">
|
||||
<button type="button" onclick="document.getElementById('file-input').click()" class="btn btn-primary">
|
||||
Выбрать файлы
|
||||
</button>
|
||||
<button id="cancel-upload" class="btn btn-secondary ml-3">
|
||||
Отмена
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Upload Progress -->
|
||||
<div id="upload-progress" class="card" style="display: none;">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Загрузка файлов</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="progress-list">
|
||||
<!-- Progress items will be added here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter and Search -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Тип файла</label>
|
||||
<select id="file-type-filter" class="form-control">
|
||||
<option value="">Все типы</option>
|
||||
<option value="image/jpeg">JPEG</option>
|
||||
<option value="image/png">PNG</option>
|
||||
<option value="image/gif">GIF</option>
|
||||
<option value="image/svg+xml">SVG</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Размер</label>
|
||||
<select id="size-filter" class="form-control">
|
||||
<option value="">Любой размер</option>
|
||||
<option value="small">Маленький (< 1MB)</option>
|
||||
<option value="medium">Средний (1-5MB)</option>
|
||||
<option value="large">Большой (> 5MB)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label>Поиск</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="search-input" placeholder="Поиск по имени файла..." class="form-control">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Media Grid -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Файлы</h3>
|
||||
<div class="card-tools">
|
||||
<span id="file-count" class="badge badge-secondary">Загрузка...</span>
|
||||
<div class="btn-group ml-2">
|
||||
<button id="grid-view" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-th-large"></i>
|
||||
</button>
|
||||
<button id="list-view" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-list"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Loading State -->
|
||||
<div id="loading" class="text-center py-5">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Загрузка...</span>
|
||||
</div>
|
||||
<p class="mt-2 text-muted">Загрузка медиа файлов...</p>
|
||||
</div>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div id="empty-state" class="text-center py-5" style="display: none;">
|
||||
<i class="fas fa-images fa-6x text-muted mb-4"></i>
|
||||
<h4 class="text-muted mb-2">Нет загруженных файлов</h4>
|
||||
<p class="text-muted mb-4">Начните с загрузки ваших первых изображений</p>
|
||||
<button onclick="document.getElementById('upload-btn').click()" class="btn btn-primary">
|
||||
<i class="fas fa-upload mr-2"></i>Загрузить файлы
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Media Grid -->
|
||||
<div id="media-grid" class="row">
|
||||
<!-- Media items will be loaded here -->
|
||||
</div>
|
||||
|
||||
<!-- Media List -->
|
||||
<div id="media-list" style="display: none;">
|
||||
<!-- List items will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="card-footer" id="pagination" style="display: none;">
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center m-0">
|
||||
<li class="page-item">
|
||||
<button id="prev-page" class="page-link">
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</button>
|
||||
</li>
|
||||
<div id="page-numbers" class="d-flex">
|
||||
<!-- Page numbers will be added here -->
|
||||
</div>
|
||||
<li class="page-item">
|
||||
<button id="next-page" class="page-link">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Media Preview Modal -->
|
||||
<div class="modal fade" id="preview-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 id="modal-title" class="modal-title">Предпросмотр файла</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<img id="modal-image" src="" alt="" class="img-fluid rounded">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label>Имя файла</label>
|
||||
<input id="modal-filename" type="text" class="form-control" readonly>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>URL</label>
|
||||
<div class="input-group">
|
||||
<input id="modal-url" type="text" class="form-control" readonly>
|
||||
<div class="input-group-append">
|
||||
<button onclick="copyToClipboard()" class="btn btn-outline-secondary" type="button">
|
||||
<i class="fas fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Размер</label>
|
||||
<p id="modal-size" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Тип</label>
|
||||
<p id="modal-type" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Ширина</label>
|
||||
<p id="modal-width" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Высота</label>
|
||||
<p id="modal-height" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Загружено</label>
|
||||
<p id="modal-date" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="btn-group d-flex">
|
||||
<button onclick="downloadFile()" class="btn btn-primary">
|
||||
<i class="fas fa-download mr-1"></i>Скачать
|
||||
</button>
|
||||
<button onclick="deleteFile()" class="btn btn-danger">
|
||||
<i class="fas fa-trash mr-1"></i>Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
class MediaGallery {
|
||||
constructor() {
|
||||
this.currentFiles = [];
|
||||
this.filteredFiles = [];
|
||||
this.currentView = 'grid';
|
||||
this.currentPage = 1;
|
||||
this.itemsPerPage = 24;
|
||||
this.currentFile = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupEventListeners();
|
||||
this.loadMedia();
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Upload button
|
||||
document.getElementById('upload-btn').addEventListener('click', () => {
|
||||
this.showUploadZone();
|
||||
});
|
||||
|
||||
// Cancel upload
|
||||
document.getElementById('cancel-upload').addEventListener('click', () => {
|
||||
this.hideUploadZone();
|
||||
});
|
||||
|
||||
// File input
|
||||
document.getElementById('file-input').addEventListener('change', (e) => {
|
||||
this.handleFiles(e.target.files);
|
||||
});
|
||||
|
||||
// Refresh button
|
||||
document.getElementById('refresh-btn').addEventListener('click', () => {
|
||||
this.loadMedia();
|
||||
});
|
||||
|
||||
// View toggle
|
||||
document.getElementById('grid-view').addEventListener('click', () => {
|
||||
this.setView('grid');
|
||||
});
|
||||
|
||||
document.getElementById('list-view').addEventListener('click', () => {
|
||||
this.setView('list');
|
||||
});
|
||||
|
||||
// Filters
|
||||
document.getElementById('file-type-filter').addEventListener('change', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
document.getElementById('size-filter').addEventListener('change', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
document.getElementById('search-input').addEventListener('input', () => {
|
||||
this.applyFilters();
|
||||
});
|
||||
|
||||
// Modal
|
||||
document.getElementById('close-modal').addEventListener('click', () => {
|
||||
this.closeModal();
|
||||
});
|
||||
|
||||
// Upload zone drag and drop
|
||||
const uploadZone = document.getElementById('upload-zone');
|
||||
uploadZone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
uploadZone.classList.add('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
uploadZone.addEventListener('dragleave', () => {
|
||||
uploadZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
uploadZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
uploadZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
this.handleFiles(e.dataTransfer.files);
|
||||
});
|
||||
}
|
||||
|
||||
async loadMedia() {
|
||||
try {
|
||||
document.getElementById('loading').style.display = 'block';
|
||||
document.getElementById('empty-state').style.display = 'none';
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
|
||||
const response = await fetch('/api/media/list');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.currentFiles = data.images || [];
|
||||
this.applyFilters();
|
||||
} else {
|
||||
throw new Error(data.message || 'Failed to load media');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading media:', error);
|
||||
this.showError('Ошибка загрузки медиа файлов');
|
||||
} finally {
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
const typeFilter = document.getElementById('file-type-filter').value;
|
||||
const sizeFilter = document.getElementById('size-filter').value;
|
||||
const searchQuery = document.getElementById('search-input').value.toLowerCase();
|
||||
|
||||
this.filteredFiles = this.currentFiles.filter(file => {
|
||||
// Type filter
|
||||
if (typeFilter && file.mimetype !== typeFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Size filter
|
||||
if (sizeFilter) {
|
||||
const sizeInMB = file.size / (1024 * 1024);
|
||||
if (sizeFilter === 'small' && sizeInMB >= 1) return false;
|
||||
if (sizeFilter === 'medium' && (sizeInMB < 1 || sizeInMB > 5)) return false;
|
||||
if (sizeFilter === 'large' && sizeInMB <= 5) return false;
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if (searchQuery && !file.filename.toLowerCase().includes(searchQuery)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.updateFileCount();
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
updateFileCount() {
|
||||
const total = this.currentFiles.length;
|
||||
const filtered = this.filteredFiles.length;
|
||||
const countText = filtered === total ?
|
||||
`${total} файлов` :
|
||||
`${filtered} из ${total} файлов`;
|
||||
|
||||
document.getElementById('file-count').textContent = countText;
|
||||
}
|
||||
|
||||
renderMedia() {
|
||||
if (this.filteredFiles.length === 0) {
|
||||
document.getElementById('empty-state').style.display = 'block';
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
document.getElementById('media-list').style.display = 'none';
|
||||
document.getElementById('pagination').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('empty-state').style.display = 'none';
|
||||
|
||||
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
|
||||
const endIndex = startIndex + this.itemsPerPage;
|
||||
const pageFiles = this.filteredFiles.slice(startIndex, endIndex);
|
||||
|
||||
if (this.currentView === 'grid') {
|
||||
this.renderGrid(pageFiles);
|
||||
} else {
|
||||
this.renderList(pageFiles);
|
||||
}
|
||||
|
||||
this.updatePagination();
|
||||
}
|
||||
|
||||
renderGrid(files) {
|
||||
document.getElementById('media-grid').style.display = 'grid';
|
||||
document.getElementById('media-list').style.display = 'none';
|
||||
|
||||
const grid = document.getElementById('media-grid');
|
||||
grid.innerHTML = files.map(file => `
|
||||
<div class="group relative bg-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow"
|
||||
onclick="mediaGallery.openModal('${file.filename}')">
|
||||
<div class="aspect-square">
|
||||
<img src="${file.url}" alt="${file.filename}"
|
||||
class="w-full h-full object-cover">
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-25 transition-opacity flex items-center justify-center">
|
||||
<div class="opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<button class="bg-white bg-opacity-90 text-gray-800 px-3 py-2 rounded-lg mr-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.downloadFile('${file.filename}')">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
<button class="bg-red-500 bg-opacity-90 text-white px-3 py-2 rounded-lg"
|
||||
onclick="event.stopPropagation(); mediaGallery.deleteFile('${file.filename}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-75 text-white p-2">
|
||||
<p class="text-xs truncate">${file.filename}</p>
|
||||
<p class="text-xs text-gray-300">${this.formatFileSize(file.size)}</p>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
renderList(files) {
|
||||
document.getElementById('media-grid').style.display = 'none';
|
||||
document.getElementById('media-list').style.display = 'block';
|
||||
|
||||
const list = document.getElementById('media-list');
|
||||
list.innerHTML = files.map(file => `
|
||||
<div class="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 cursor-pointer"
|
||||
onclick="mediaGallery.openModal('${file.filename}')">
|
||||
<div class="w-16 h-16 flex-shrink-0 mr-4">
|
||||
<img src="${file.url}" alt="${file.filename}"
|
||||
class="w-full h-full object-cover rounded">
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h4 class="text-sm font-medium text-gray-900 truncate">${file.filename}</h4>
|
||||
<p class="text-sm text-gray-500">${this.formatFileSize(file.size)} • ${file.mimetype}</p>
|
||||
<p class="text-xs text-gray-400">${new Date(file.uploadedAt).toLocaleDateString('ru-RU')}</p>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<button class="text-blue-600 hover:text-blue-800 p-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.downloadFile('${file.filename}')">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
<button class="text-red-600 hover:text-red-800 p-2"
|
||||
onclick="event.stopPropagation(); mediaGallery.deleteFile('${file.filename}')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
setView(view) {
|
||||
this.currentView = view;
|
||||
|
||||
// Update button states
|
||||
document.getElementById('grid-view').classList.toggle('bg-blue-600', view === 'grid');
|
||||
document.getElementById('grid-view').classList.toggle('text-white', view === 'grid');
|
||||
document.getElementById('list-view').classList.toggle('bg-blue-600', view === 'list');
|
||||
document.getElementById('list-view').classList.toggle('text-white', view === 'list');
|
||||
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
showUploadZone() {
|
||||
document.getElementById('upload-zone').style.display = 'block';
|
||||
}
|
||||
|
||||
hideUploadZone() {
|
||||
document.getElementById('upload-zone').style.display = 'none';
|
||||
document.getElementById('file-input').value = '';
|
||||
}
|
||||
|
||||
async handleFiles(files) {
|
||||
const validFiles = Array.from(files).filter(file => {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
this.showError(`${file.name} не является изображением`);
|
||||
return false;
|
||||
}
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
this.showError(`${file.name} слишком большой (максимум 10MB)`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (validFiles.length === 0) return;
|
||||
|
||||
this.hideUploadZone();
|
||||
await this.uploadFiles(validFiles);
|
||||
}
|
||||
|
||||
async uploadFiles(files) {
|
||||
const progressContainer = document.getElementById('upload-progress');
|
||||
const progressList = document.getElementById('progress-list');
|
||||
|
||||
progressContainer.style.display = 'block';
|
||||
progressList.innerHTML = '';
|
||||
|
||||
for (const file of files) {
|
||||
const progressItem = this.createProgressItem(file);
|
||||
progressList.appendChild(progressItem);
|
||||
|
||||
try {
|
||||
await this.uploadSingleFile(file, progressItem);
|
||||
} catch (error) {
|
||||
this.updateProgressItem(progressItem, 'error', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
progressContainer.style.display = 'none';
|
||||
this.loadMedia();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
createProgressItem(file) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'flex items-center justify-between p-3 bg-gray-50 rounded';
|
||||
div.innerHTML = `
|
||||
<div class="flex items-center space-x-3">
|
||||
<i class="fas fa-image text-gray-400"></i>
|
||||
<span class="text-sm text-gray-900">${file.name}</span>
|
||||
<span class="text-xs text-gray-500">${this.formatFileSize(file.size)}</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-32 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-blue-600 h-2 rounded-full progress-bar" style="width: 0%"></div>
|
||||
</div>
|
||||
<span class="text-sm text-gray-600 status">0%</span>
|
||||
</div>
|
||||
`;
|
||||
return div;
|
||||
}
|
||||
|
||||
updateProgressItem(item, status, message = '') {
|
||||
const statusElement = item.querySelector('.status');
|
||||
const progressBar = item.querySelector('.progress-bar');
|
||||
|
||||
if (status === 'error') {
|
||||
statusElement.textContent = 'Ошибка';
|
||||
statusElement.className = 'text-sm text-red-600 status';
|
||||
progressBar.className = 'bg-red-600 h-2 rounded-full progress-bar';
|
||||
progressBar.style.width = '100%';
|
||||
} else if (status === 'success') {
|
||||
statusElement.textContent = 'Готово';
|
||||
statusElement.className = 'text-sm text-green-600 status';
|
||||
progressBar.className = 'bg-green-600 h-2 rounded-full progress-bar';
|
||||
progressBar.style.width = '100%';
|
||||
}
|
||||
}
|
||||
|
||||
async uploadSingleFile(file, progressItem) {
|
||||
const formData = new FormData();
|
||||
formData.append('images', file);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
const progressBar = progressItem.querySelector('.progress-bar');
|
||||
const status = progressItem.querySelector('.status');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
xhr.upload.addEventListener('progress', (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = (e.loaded / e.total) * 100;
|
||||
progressBar.style.width = percentComplete + '%';
|
||||
status.textContent = Math.round(percentComplete) + '%';
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status === 200) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
if (response.success) {
|
||||
this.updateProgressItem(progressItem, 'success');
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(response.message));
|
||||
}
|
||||
} else {
|
||||
reject(new Error('Upload failed'));
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
reject(new Error('Network error'));
|
||||
});
|
||||
|
||||
xhr.open('POST', '/api/media/upload-multiple');
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
openModal(filename) {
|
||||
const file = this.currentFiles.find(f => f.filename === filename);
|
||||
if (!file) return;
|
||||
|
||||
this.currentFile = file;
|
||||
|
||||
document.getElementById('modal-title').textContent = file.filename;
|
||||
document.getElementById('modal-image').src = file.url;
|
||||
document.getElementById('modal-filename').value = file.filename;
|
||||
document.getElementById('modal-url').value = window.location.origin + file.url;
|
||||
document.getElementById('modal-size').textContent = this.formatFileSize(file.size);
|
||||
document.getElementById('modal-type').textContent = file.mimetype;
|
||||
document.getElementById('modal-date').textContent = new Date(file.uploadedAt).toLocaleDateString('ru-RU');
|
||||
|
||||
// Load image to get dimensions
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
document.getElementById('modal-width').textContent = img.width + 'px';
|
||||
document.getElementById('modal-height').textContent = img.height + 'px';
|
||||
};
|
||||
img.src = file.url;
|
||||
|
||||
document.getElementById('preview-modal').style.display = 'flex';
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
document.getElementById('preview-modal').style.display = 'none';
|
||||
this.currentFile = null;
|
||||
}
|
||||
|
||||
async deleteFile(filename) {
|
||||
if (!confirm(`Вы уверены, что хотите удалить файл "${filename}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/media/${filename}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
this.showSuccess('Файл удален');
|
||||
this.loadMedia();
|
||||
if (this.currentFile && this.currentFile.filename === filename) {
|
||||
this.closeModal();
|
||||
}
|
||||
} else {
|
||||
throw new Error('Failed to delete file');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting file:', error);
|
||||
this.showError('Ошибка удаления файла');
|
||||
}
|
||||
}
|
||||
|
||||
downloadFile(filename) {
|
||||
const file = filename ?
|
||||
this.currentFiles.find(f => f.filename === filename) :
|
||||
this.currentFile;
|
||||
|
||||
if (!file) return;
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = file.url;
|
||||
link.download = file.filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
updatePagination() {
|
||||
const totalPages = Math.ceil(this.filteredFiles.length / this.itemsPerPage);
|
||||
|
||||
if (totalPages <= 1) {
|
||||
document.getElementById('pagination').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('pagination').style.display = 'block';
|
||||
|
||||
// Update prev/next buttons
|
||||
document.getElementById('prev-page').disabled = this.currentPage === 1;
|
||||
document.getElementById('next-page').disabled = this.currentPage === totalPages;
|
||||
|
||||
// Update page numbers
|
||||
const pageNumbers = document.getElementById('page-numbers');
|
||||
pageNumbers.innerHTML = '';
|
||||
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
if (i === 1 || i === totalPages || (i >= this.currentPage - 2 && i <= this.currentPage + 2)) {
|
||||
const button = document.createElement('button');
|
||||
button.className = `px-3 py-2 rounded ${
|
||||
i === this.currentPage ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-600 hover:bg-gray-300'
|
||||
}`;
|
||||
button.textContent = i;
|
||||
button.onclick = () => this.goToPage(i);
|
||||
pageNumbers.appendChild(button);
|
||||
} else if (i === this.currentPage - 3 || i === this.currentPage + 3) {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'px-2 py-2 text-gray-400';
|
||||
span.textContent = '...';
|
||||
pageNumbers.appendChild(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goToPage(page) {
|
||||
this.currentPage = page;
|
||||
this.renderMedia();
|
||||
}
|
||||
|
||||
formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
this.showNotification(message, 'error');
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this.showNotification(message, 'success');
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `fixed top-4 right-4 px-6 py-3 rounded-lg text-white z-50 ${
|
||||
type === 'success' ? 'bg-green-500' :
|
||||
type === 'error' ? 'bg-red-500' : 'bg-blue-500'
|
||||
}`;
|
||||
notification.textContent = message;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.remove();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// Global functions for modal
|
||||
function copyToClipboard() {
|
||||
const urlInput = document.getElementById('modal-url');
|
||||
urlInput.select();
|
||||
document.execCommand('copy');
|
||||
mediaGallery.showSuccess('URL скопирован в буфер обмена');
|
||||
}
|
||||
|
||||
function downloadFile() {
|
||||
mediaGallery.downloadFile();
|
||||
}
|
||||
|
||||
function deleteFile() {
|
||||
if (mediaGallery.currentFile) {
|
||||
mediaGallery.deleteFile(mediaGallery.currentFile.filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
let mediaGallery;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
mediaGallery = new MediaGallery();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1251
.history/views/admin/media_20251026214344.ejs
Normal file
1251
.history/views/admin/media_20251026214344.ejs
Normal file
File diff suppressed because it is too large
Load Diff
1251
.history/views/admin/media_20251026214418.ejs
Normal file
1251
.history/views/admin/media_20251026214418.ejs
Normal file
File diff suppressed because it is too large
Load Diff
362
.history/views/admin/portfolio/list_20251026221344.ejs
Normal file
362
.history/views/admin/portfolio/list_20251026221344.ejs
Normal file
@@ -0,0 +1,362 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-briefcase mr-2"></i>Управление портфолио</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Портфолио</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search and Filter Bar -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<input type="text" id="searchInput" class="form-control" placeholder="Поиск проектов...">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="searchProjects()">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select id="categoryFilter" class="form-control" onchange="filterByCategory()">
|
||||
<option value="">Все категории</option>
|
||||
<option value="web-development">Веб-разработка</option>
|
||||
<option value="mobile-app">Мобильное приложение</option>
|
||||
<option value="ui-ux-design">UI/UX дизайн</option>
|
||||
<option value="e-commerce">E-commerce</option>
|
||||
<option value="enterprise">Корпоративное</option>
|
||||
<option value="other">Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select id="statusFilter" class="form-control" onchange="filterByStatus()">
|
||||
<option value="">Все статусы</option>
|
||||
<option value="published">Опубликовано</option>
|
||||
<option value="draft">Черновик</option>
|
||||
<option value="featured">Рекомендуемое</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 text-right">
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить проект
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Table -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Список проектов</h3>
|
||||
<div class="card-tools">
|
||||
<span class="badge badge-secondary" id="projectCount">
|
||||
Всего: <%= portfolio ? portfolio.length : 0 %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body table-responsive p-0">
|
||||
<table class="table table-hover text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60px;">Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Категория</th>
|
||||
<th>Статус</th>
|
||||
<th>Технологии</th>
|
||||
<th>Создано</th>
|
||||
<th style="width: 150px;">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if (portfolio && portfolio.length > 0) { %>
|
||||
<% portfolio.forEach(item => { %>
|
||||
<tr class="portfolio-item" data-category="<%= item.category %>" data-title="<%= item.title.toLowerCase() %>" data-status="<%= item.isPublished ? 'published' : 'draft' %><%= item.featured ? ' featured' : '' %>">
|
||||
<td>
|
||||
<% if (item.images && item.images.length > 0) { %>
|
||||
<img src="<%= item.images[0].url %>" alt="<%= item.title %>" class="img-circle img-size-32">
|
||||
<% } else { %>
|
||||
<div class="img-circle bg-secondary d-flex align-items-center justify-content-center" style="width: 32px; height: 32px;">
|
||||
<i class="fas fa-image text-white"></i>
|
||||
</div>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<strong><%= item.title %></strong>
|
||||
<% if (item.featured) { %>
|
||||
<span class="badge badge-warning ml-1">
|
||||
<i class="fas fa-star"></i>
|
||||
</span>
|
||||
<% } %>
|
||||
</div>
|
||||
<small class="text-muted"><%= item.shortDescription || 'Описание не указано' %></small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info">
|
||||
<%= item.category.replace('-', ' ') %>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<% if (item.isPublished) { %>
|
||||
<span class="badge badge-success">
|
||||
<i class="fas fa-check-circle mr-1"></i>Опубликовано
|
||||
</span>
|
||||
<% } else { %>
|
||||
<span class="badge badge-secondary">
|
||||
<i class="fas fa-clock mr-1"></i>Черновик
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (item.technologies && item.technologies.length > 0) { %>
|
||||
<% item.technologies.slice(0, 2).forEach(tech => { %>
|
||||
<span class="badge badge-light mr-1"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% if (item.technologies.length > 2) { %>
|
||||
<span class="text-muted">+<%= item.technologies.length - 2 %></span>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<span class="text-muted">—</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<small class="text-muted">
|
||||
<%= new Date(item.createdAt).toLocaleDateString('ru-RU') %>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<% if (item.isPublished) { %>
|
||||
<a href="/portfolio/<%= item.id %>" target="_blank" class="btn btn-info btn-sm" title="Просмотр">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
<% } %>
|
||||
<button type="button" class="btn btn-<%= item.isPublished ? 'warning' : 'success' %> btn-sm"
|
||||
onclick="togglePublish('<%= item.id %>', '<%= item.isPublished %>')"
|
||||
title="<%= item.isPublished ? 'Скрыть' : 'Опубликовать' %>">
|
||||
<i class="fas <%= item.isPublished ? 'fa-eye-slash' : 'fa-eye' %>"></i>
|
||||
</button>
|
||||
<a href="/admin/portfolio/edit/<%= item.id %>" class="btn btn-primary btn-sm" title="Редактировать">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger btn-sm"
|
||||
onclick="deletePortfolio('<%= item.id %>', '<%= item.title %>')"
|
||||
title="Удалить">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<tr>
|
||||
<td colspan="7" class="text-center py-4">
|
||||
<div class="text-muted">
|
||||
<i class="fas fa-briefcase fa-3x mb-3"></i>
|
||||
<p>Проекты не найдены</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
Добавить первый проект
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Pagination -->
|
||||
<% if (pagination && pagination.total > 1) { %>
|
||||
<div class="card-footer clearfix">
|
||||
<ul class="pagination pagination-sm m-0 float-right">
|
||||
<% if (pagination.hasPrev) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current - 1 %>">«</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% for (let i = 1; i <= pagination.total; i++) { %>
|
||||
<li class="page-item <%= pagination.current === i ? 'active' : '' %>">
|
||||
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (pagination.hasNext) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current + 1 %>">»</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function deletePortfolio(id, title) {
|
||||
Swal.fire({
|
||||
title: 'Удалить проект?',
|
||||
text: `Вы уверены, что хотите удалить проект "${title}"?`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/portfolio/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Проект был удален.', 'success').then(() => {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении проекта', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении проекта', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function togglePublish(id, currentStatus) {
|
||||
const isPublished = currentStatus === 'true';
|
||||
|
||||
fetch(`/api/admin/portfolio/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
isPublished: !isPublished
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
toastr.success(`Проект ${!isPublished ? 'опубликован' : 'скрыт'}`);
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 1000);
|
||||
} else {
|
||||
toastr.error(data.message || 'Ошибка при изменении статуса');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при изменении статуса');
|
||||
});
|
||||
}
|
||||
|
||||
function searchProjects() {
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
const items = document.querySelectorAll('.portfolio-item');
|
||||
let visibleCount = 0;
|
||||
|
||||
items.forEach(item => {
|
||||
const title = item.dataset.title;
|
||||
if (title.includes(searchTerm)) {
|
||||
item.style.display = 'table-row';
|
||||
visibleCount++;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
updateProjectCount(visibleCount, items.length);
|
||||
}
|
||||
|
||||
function filterByCategory() {
|
||||
const selectedCategory = document.getElementById('categoryFilter').value;
|
||||
const selectedStatus = document.getElementById('statusFilter').value;
|
||||
filterPortfolio(selectedCategory, selectedStatus);
|
||||
}
|
||||
|
||||
function filterByStatus() {
|
||||
const selectedCategory = document.getElementById('categoryFilter').value;
|
||||
const selectedStatus = document.getElementById('statusFilter').value;
|
||||
filterPortfolio(selectedCategory, selectedStatus);
|
||||
}
|
||||
|
||||
function filterPortfolio(category, status) {
|
||||
const items = document.querySelectorAll('.portfolio-item');
|
||||
let visibleCount = 0;
|
||||
|
||||
items.forEach(item => {
|
||||
const itemCategory = item.dataset.category;
|
||||
const itemStatus = item.dataset.status;
|
||||
|
||||
let showItem = true;
|
||||
|
||||
if (category && itemCategory !== category) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
if (status && !itemStatus.includes(status)) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
if (showItem) {
|
||||
item.style.display = 'table-row';
|
||||
visibleCount++;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
updateProjectCount(visibleCount, items.length);
|
||||
}
|
||||
|
||||
function updateProjectCount(visible, total) {
|
||||
const countElement = document.getElementById('projectCount');
|
||||
if (countElement) {
|
||||
if (visible !== undefined) {
|
||||
countElement.textContent = `Показано: ${visible} из ${total}`;
|
||||
} else {
|
||||
countElement.textContent = `Всего: ${total}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search on Enter key
|
||||
document.getElementById('searchInput').addEventListener('keyup', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
searchProjects();
|
||||
}
|
||||
});
|
||||
|
||||
// Auto search on input
|
||||
document.getElementById('searchInput').addEventListener('input', function() {
|
||||
searchProjects();
|
||||
});
|
||||
</script>
|
||||
362
.history/views/admin/portfolio/list_20251026221355.ejs
Normal file
362
.history/views/admin/portfolio/list_20251026221355.ejs
Normal file
@@ -0,0 +1,362 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-briefcase mr-2"></i>Управление портфолио</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Портфолио</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search and Filter Bar -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<input type="text" id="searchInput" class="form-control" placeholder="Поиск проектов...">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="searchProjects()">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select id="categoryFilter" class="form-control" onchange="filterByCategory()">
|
||||
<option value="">Все категории</option>
|
||||
<option value="web-development">Веб-разработка</option>
|
||||
<option value="mobile-app">Мобильное приложение</option>
|
||||
<option value="ui-ux-design">UI/UX дизайн</option>
|
||||
<option value="e-commerce">E-commerce</option>
|
||||
<option value="enterprise">Корпоративное</option>
|
||||
<option value="other">Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select id="statusFilter" class="form-control" onchange="filterByStatus()">
|
||||
<option value="">Все статусы</option>
|
||||
<option value="published">Опубликовано</option>
|
||||
<option value="draft">Черновик</option>
|
||||
<option value="featured">Рекомендуемое</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 text-right">
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить проект
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Table -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Список проектов</h3>
|
||||
<div class="card-tools">
|
||||
<span class="badge badge-secondary" id="projectCount">
|
||||
Всего: <%= portfolio ? portfolio.length : 0 %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body table-responsive p-0">
|
||||
<table class="table table-hover text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60px;">Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Категория</th>
|
||||
<th>Статус</th>
|
||||
<th>Технологии</th>
|
||||
<th>Создано</th>
|
||||
<th style="width: 150px;">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if (portfolio && portfolio.length > 0) { %>
|
||||
<% portfolio.forEach(item => { %>
|
||||
<tr class="portfolio-item" data-category="<%= item.category %>" data-title="<%= item.title.toLowerCase() %>" data-status="<%= item.isPublished ? 'published' : 'draft' %><%= item.featured ? ' featured' : '' %>">
|
||||
<td>
|
||||
<% if (item.images && item.images.length > 0) { %>
|
||||
<img src="<%= item.images[0].url %>" alt="<%= item.title %>" class="img-circle img-size-32">
|
||||
<% } else { %>
|
||||
<div class="img-circle bg-secondary d-flex align-items-center justify-content-center" style="width: 32px; height: 32px;">
|
||||
<i class="fas fa-image text-white"></i>
|
||||
</div>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<strong><%= item.title %></strong>
|
||||
<% if (item.featured) { %>
|
||||
<span class="badge badge-warning ml-1">
|
||||
<i class="fas fa-star"></i>
|
||||
</span>
|
||||
<% } %>
|
||||
</div>
|
||||
<small class="text-muted"><%= item.shortDescription || 'Описание не указано' %></small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info">
|
||||
<%= item.category.replace('-', ' ') %>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<% if (item.isPublished) { %>
|
||||
<span class="badge badge-success">
|
||||
<i class="fas fa-check-circle mr-1"></i>Опубликовано
|
||||
</span>
|
||||
<% } else { %>
|
||||
<span class="badge badge-secondary">
|
||||
<i class="fas fa-clock mr-1"></i>Черновик
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (item.technologies && item.technologies.length > 0) { %>
|
||||
<% item.technologies.slice(0, 2).forEach(tech => { %>
|
||||
<span class="badge badge-light mr-1"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% if (item.technologies.length > 2) { %>
|
||||
<span class="text-muted">+<%= item.technologies.length - 2 %></span>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<span class="text-muted">—</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<small class="text-muted">
|
||||
<%= new Date(item.createdAt).toLocaleDateString('ru-RU') %>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<% if (item.isPublished) { %>
|
||||
<a href="/portfolio/<%= item.id %>" target="_blank" class="btn btn-info btn-sm" title="Просмотр">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
<% } %>
|
||||
<button type="button" class="btn btn-<%= item.isPublished ? 'warning' : 'success' %> btn-sm"
|
||||
onclick="togglePublish('<%= item.id %>', '<%= item.isPublished %>')"
|
||||
title="<%= item.isPublished ? 'Скрыть' : 'Опубликовать' %>">
|
||||
<i class="fas <%= item.isPublished ? 'fa-eye-slash' : 'fa-eye' %>"></i>
|
||||
</button>
|
||||
<a href="/admin/portfolio/edit/<%= item.id %>" class="btn btn-primary btn-sm" title="Редактировать">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger btn-sm"
|
||||
onclick="deletePortfolio('<%= item.id %>', '<%= item.title %>')"
|
||||
title="Удалить">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<tr>
|
||||
<td colspan="7" class="text-center py-4">
|
||||
<div class="text-muted">
|
||||
<i class="fas fa-briefcase fa-3x mb-3"></i>
|
||||
<p>Проекты не найдены</p>
|
||||
<a href="/admin/portfolio/add" class="btn btn-primary">
|
||||
Добавить первый проект
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Pagination -->
|
||||
<% if (pagination && pagination.total > 1) { %>
|
||||
<div class="card-footer clearfix">
|
||||
<ul class="pagination pagination-sm m-0 float-right">
|
||||
<% if (pagination.hasPrev) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current - 1 %>">«</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% for (let i = 1; i <= pagination.total; i++) { %>
|
||||
<li class="page-item <%= pagination.current === i ? 'active' : '' %>">
|
||||
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (pagination.hasNext) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current + 1 %>">»</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function deletePortfolio(id, title) {
|
||||
Swal.fire({
|
||||
title: 'Удалить проект?',
|
||||
text: `Вы уверены, что хотите удалить проект "${title}"?`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/portfolio/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Проект был удален.', 'success').then(() => {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении проекта', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении проекта', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function togglePublish(id, currentStatus) {
|
||||
const isPublished = currentStatus === 'true';
|
||||
|
||||
fetch(`/api/admin/portfolio/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
isPublished: !isPublished
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
toastr.success(`Проект ${!isPublished ? 'опубликован' : 'скрыт'}`);
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 1000);
|
||||
} else {
|
||||
toastr.error(data.message || 'Ошибка при изменении статуса');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при изменении статуса');
|
||||
});
|
||||
}
|
||||
|
||||
function searchProjects() {
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
const items = document.querySelectorAll('.portfolio-item');
|
||||
let visibleCount = 0;
|
||||
|
||||
items.forEach(item => {
|
||||
const title = item.dataset.title;
|
||||
if (title.includes(searchTerm)) {
|
||||
item.style.display = 'table-row';
|
||||
visibleCount++;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
updateProjectCount(visibleCount, items.length);
|
||||
}
|
||||
|
||||
function filterByCategory() {
|
||||
const selectedCategory = document.getElementById('categoryFilter').value;
|
||||
const selectedStatus = document.getElementById('statusFilter').value;
|
||||
filterPortfolio(selectedCategory, selectedStatus);
|
||||
}
|
||||
|
||||
function filterByStatus() {
|
||||
const selectedCategory = document.getElementById('categoryFilter').value;
|
||||
const selectedStatus = document.getElementById('statusFilter').value;
|
||||
filterPortfolio(selectedCategory, selectedStatus);
|
||||
}
|
||||
|
||||
function filterPortfolio(category, status) {
|
||||
const items = document.querySelectorAll('.portfolio-item');
|
||||
let visibleCount = 0;
|
||||
|
||||
items.forEach(item => {
|
||||
const itemCategory = item.dataset.category;
|
||||
const itemStatus = item.dataset.status;
|
||||
|
||||
let showItem = true;
|
||||
|
||||
if (category && itemCategory !== category) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
if (status && !itemStatus.includes(status)) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
if (showItem) {
|
||||
item.style.display = 'table-row';
|
||||
visibleCount++;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
updateProjectCount(visibleCount, items.length);
|
||||
}
|
||||
|
||||
function updateProjectCount(visible, total) {
|
||||
const countElement = document.getElementById('projectCount');
|
||||
if (countElement) {
|
||||
if (visible !== undefined) {
|
||||
countElement.textContent = `Показано: ${visible} из ${total}`;
|
||||
} else {
|
||||
countElement.textContent = `Всего: ${total}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search on Enter key
|
||||
document.getElementById('searchInput').addEventListener('keyup', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
searchProjects();
|
||||
}
|
||||
});
|
||||
|
||||
// Auto search on input
|
||||
document.getElementById('searchInput').addEventListener('input', function() {
|
||||
searchProjects();
|
||||
});
|
||||
</script>
|
||||
344
.history/views/admin/services/add_20251026220815.ejs
Normal file
344
.history/views/admin/services/add_20251026220815.ejs
Normal file
@@ -0,0 +1,344 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-plus mr-2"></i>Добавить услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Добавить</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm" action="/api/admin/services" method="POST">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2" placeholder="Краткое описание для списков и карточек"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6" placeholder="Детальное описание услуги"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development">Веб-разработка</option>
|
||||
<option value="mobile-development">Мобильная разработка</option>
|
||||
<option value="ui-ux-design">UI/UX Дизайн</option>
|
||||
<option value="consulting">Консалтинг</option>
|
||||
<option value="support">Поддержка</option>
|
||||
<option value="other">Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" placeholder="fas fa-code" value="fas fa-cog">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" placeholder="2-4 недели">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD">USD ($)</option>
|
||||
<option value="EUR">EUR (€)</option>
|
||||
<option value="KRW">KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed">Фиксированная цена</option>
|
||||
<option value="hourly">Почасовая оплата</option>
|
||||
<option value="project">За проект</option>
|
||||
<option value="subscription">Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" checked>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured">
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="0" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" placeholder="веб-дизайн, frontend, react">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" placeholder="через, запятую">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить услугу
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
let featureIndex = 1;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch('/api/admin/services', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно создана!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при создании услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при создании услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
344
.history/views/admin/services/add_20251026220932.ejs
Normal file
344
.history/views/admin/services/add_20251026220932.ejs
Normal file
@@ -0,0 +1,344 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-plus mr-2"></i>Добавить услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Добавить</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm" action="/api/admin/services" method="POST">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2" placeholder="Краткое описание для списков и карточек"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6" placeholder="Детальное описание услуги"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development">Веб-разработка</option>
|
||||
<option value="mobile-development">Мобильная разработка</option>
|
||||
<option value="ui-ux-design">UI/UX Дизайн</option>
|
||||
<option value="consulting">Консалтинг</option>
|
||||
<option value="support">Поддержка</option>
|
||||
<option value="other">Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" placeholder="fas fa-code" value="fas fa-cog">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" placeholder="2-4 недели">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD">USD ($)</option>
|
||||
<option value="EUR">EUR (€)</option>
|
||||
<option value="KRW">KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed">Фиксированная цена</option>
|
||||
<option value="hourly">Почасовая оплата</option>
|
||||
<option value="project">За проект</option>
|
||||
<option value="subscription">Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" checked>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured">
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="0" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" placeholder="веб-дизайн, frontend, react">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" placeholder="через, запятую">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить услугу
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
let featureIndex = 1;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch('/api/admin/services', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно создана!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при создании услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при создании услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
410
.history/views/admin/services/edit_20251026220907.ejs
Normal file
410
.history/views/admin/services/edit_20251026220907.ejs
Normal file
@@ -0,0 +1,410 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-edit mr-2"></i>Редактировать услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Редактировать</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm">
|
||||
<input type="hidden" id="serviceId" value="<%= service.id %>">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
|
||||
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
|
||||
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
|
||||
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
|
||||
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
|
||||
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
|
||||
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
|
||||
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
|
||||
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
|
||||
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
|
||||
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<% if (service.features && service.features.length > 0) { %>
|
||||
<% service.features.forEach((feature, index) => { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[<%= index %>][included]">
|
||||
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
|
||||
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить изменения
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
|
||||
<i class="fas fa-trash mr-1"></i> Удалить услугу
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
let featureIndex = <%= service.features ? service.features.length : 1 %>;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const serviceId = $('#serviceId').val();
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно обновлена!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при обновлении услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при обновлении услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteService() {
|
||||
const serviceId = $('#serviceId').val();
|
||||
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
window.location.href = '/admin/services';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
410
.history/views/admin/services/edit_20251026220932.ejs
Normal file
410
.history/views/admin/services/edit_20251026220932.ejs
Normal file
@@ -0,0 +1,410 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-edit mr-2"></i>Редактировать услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Редактировать</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm">
|
||||
<input type="hidden" id="serviceId" value="<%= service.id %>">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
|
||||
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
|
||||
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
|
||||
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
|
||||
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
|
||||
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
|
||||
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
|
||||
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
|
||||
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
|
||||
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
|
||||
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<% if (service.features && service.features.length > 0) { %>
|
||||
<% service.features.forEach((feature, index) => { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[<%= index %>][included]">
|
||||
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
|
||||
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить изменения
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
|
||||
<i class="fas fa-trash mr-1"></i> Удалить услугу
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
let featureIndex = <%= service.features ? service.features.length : 1 %>;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const serviceId = $('#serviceId').val();
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно обновлена!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при обновлении услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при обновлении услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteService() {
|
||||
const serviceId = $('#serviceId').val();
|
||||
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
window.location.href = '/admin/services';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
410
.history/views/admin/services/edit_20251026221027.ejs
Normal file
410
.history/views/admin/services/edit_20251026221027.ejs
Normal file
@@ -0,0 +1,410 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-edit mr-2"></i>Редактировать услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Редактировать</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm">
|
||||
<input type="hidden" id="serviceId" value="<%= service.id %>">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
|
||||
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
|
||||
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
|
||||
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
|
||||
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
|
||||
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
|
||||
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
|
||||
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
|
||||
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
|
||||
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
|
||||
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<% if (service.features && service.features.length > 0) { %>
|
||||
<% service.features.forEach((feature, index) => { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[<%= index %>][included]">
|
||||
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
|
||||
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить изменения
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
|
||||
<i class="fas fa-trash mr-1"></i> Удалить услугу
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
let featureIndex = <% if (service.features && service.features.length) { %><%= service.features.length %><% } else { %>1<% } %>;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const serviceId = $('#serviceId').val();
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно обновлена!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при обновлении услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при обновлении услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteService() {
|
||||
const serviceId = $('#serviceId').val();
|
||||
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
window.location.href = '/admin/services';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
411
.history/views/admin/services/edit_20251026221035.ejs
Normal file
411
.history/views/admin/services/edit_20251026221035.ejs
Normal file
@@ -0,0 +1,411 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-edit mr-2"></i>Редактировать услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Редактировать</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm">
|
||||
<input type="hidden" id="serviceId" value="<%= service.id %>">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
|
||||
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
|
||||
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
|
||||
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
|
||||
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
|
||||
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
|
||||
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
|
||||
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
|
||||
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
|
||||
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
|
||||
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<% if (service.features && service.features.length > 0) { %>
|
||||
<% service.features.forEach((feature, index) => { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[<%= index %>][included]">
|
||||
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
|
||||
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить изменения
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
|
||||
<i class="fas fa-trash mr-1"></i> Удалить услугу
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const service = <%- JSON.stringify(service) %>;
|
||||
let featureIndex = service.features ? service.features.length : 1;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const serviceId = $('#serviceId').val();
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно обновлена!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при обновлении услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при обновлении услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteService() {
|
||||
const serviceId = $('#serviceId').val();
|
||||
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
window.location.href = '/admin/services';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
411
.history/views/admin/services/edit_20251026221118.ejs
Normal file
411
.history/views/admin/services/edit_20251026221118.ejs
Normal file
@@ -0,0 +1,411 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-edit mr-2"></i>Редактировать услугу</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin/dashboard">Админ</a></li>
|
||||
<li class="breadcrumb-item"><a href="/admin/services">Услуги</a></li>
|
||||
<li class="breadcrumb-item active">Редактировать</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<form id="serviceForm">
|
||||
<input type="hidden" id="serviceId" value="<%= service.id %>">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<!-- Basic Information -->
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Название услуги *</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<%= service.name %>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="shortDescription">Краткое описание</label>
|
||||
<textarea class="form-control" id="shortDescription" name="shortDescription" rows="2"><%= service.shortDescription || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Полное описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="6"><%= service.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория *</label>
|
||||
<select class="form-control" id="category" name="category" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="web-development" <%= service.category === 'web-development' ? 'selected' : '' %>>Веб-разработка</option>
|
||||
<option value="mobile-development" <%= service.category === 'mobile-development' ? 'selected' : '' %>>Мобильная разработка</option>
|
||||
<option value="ui-ux-design" <%= service.category === 'ui-ux-design' ? 'selected' : '' %>>UI/UX Дизайн</option>
|
||||
<option value="consulting" <%= service.category === 'consulting' ? 'selected' : '' %>>Консалтинг</option>
|
||||
<option value="support" <%= service.category === 'support' ? 'selected' : '' %>>Поддержка</option>
|
||||
<option value="other" <%= service.category === 'other' ? 'selected' : '' %>>Другое</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="icon">Иконка</label>
|
||||
<input type="text" class="form-control" id="icon" name="icon" value="<%= service.icon || 'fas fa-cog' %>">
|
||||
<small class="form-text text-muted">FontAwesome класс иконки</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="estimatedTime">Время выполнения</label>
|
||||
<input type="text" class="form-control" id="estimatedTime" name="estimatedTime" value="<%= service.estimatedTime || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="card card-info">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Ценообразование</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="basePrice">Базовая цена ($)</label>
|
||||
<input type="number" class="form-control" id="basePrice" name="pricing[basePrice]" value="<%= service.pricing?.basePrice || '' %>" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="currency">Валюта</label>
|
||||
<select class="form-control" id="currency" name="pricing[currency]">
|
||||
<option value="USD" <%= service.pricing?.currency === 'USD' ? 'selected' : '' %>>USD ($)</option>
|
||||
<option value="EUR" <%= service.pricing?.currency === 'EUR' ? 'selected' : '' %>>EUR (€)</option>
|
||||
<option value="KRW" <%= service.pricing?.currency === 'KRW' ? 'selected' : '' %>>KRW (₩)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="pricingType">Тип ценообразования</label>
|
||||
<select class="form-control" id="pricingType" name="pricing[type]">
|
||||
<option value="fixed" <%= service.pricing?.type === 'fixed' ? 'selected' : '' %>>Фиксированная цена</option>
|
||||
<option value="hourly" <%= service.pricing?.type === 'hourly' ? 'selected' : '' %>>Почасовая оплата</option>
|
||||
<option value="project" <%= service.pricing?.type === 'project' ? 'selected' : '' %>>За проект</option>
|
||||
<option value="subscription" <%= service.pricing?.type === 'subscription' ? 'selected' : '' %>>Подписка</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Функции и возможности</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="featuresContainer">
|
||||
<% if (service.features && service.features.length > 0) { %>
|
||||
<% service.features.forEach((feature, index) => { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[<%= index %>][name]" value="<%= feature.name %>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[<%= index %>][included]">
|
||||
<option value="true" <%= feature.included ? 'selected' : '' %>>Включено</option>
|
||||
<option value="false" <%= !feature.included ? 'selected' : '' %>>Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[0][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[0][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="addFeature">
|
||||
<i class="fas fa-plus mr-1"></i> Добавить функцию
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Status & Settings -->
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="isActive" name="isActive" <%= service.isActive ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="isActive">Активная услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="featured" name="featured" <%= service.featured ? 'checked' : '' %>>
|
||||
<label class="custom-control-label" for="featured">Рекомендуемая услуга</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="order">Порядок отображения</label>
|
||||
<input type="number" class="form-control" id="order" name="order" value="<%= service.order || 0 %>" min="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Теги</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="tags">Теги (через запятую)</label>
|
||||
<input type="text" class="form-control" id="tags" name="tags" value="<%= service.tags ? service.tags.join(', ') : '' %>">
|
||||
<small class="form-text text-muted">Разделите теги запятыми</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEO -->
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="seoTitle">SEO заголовок</label>
|
||||
<input type="text" class="form-control" id="seoTitle" name="seo[title]" value="<%= service.seo?.title || '' %>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoDescription">SEO описание</label>
|
||||
<textarea class="form-control" id="seoDescription" name="seo[description]" rows="3"><%= service.seo?.description || '' %></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="seoKeywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="seoKeywords" name="seo[keywords]" value="<%= service.seo?.keywords || '' %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Сохранить изменения
|
||||
</button>
|
||||
<a href="/admin/services" class="btn btn-secondary ml-2">
|
||||
<i class="fas fa-times mr-1"></i> Отмена
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger ml-2" onclick="deleteService()">
|
||||
<i class="fas fa-trash mr-1"></i> Удалить услугу
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const service = <%- JSON.stringify(service) %>;
|
||||
let featureIndex = service.features ? service.features.length : 1;
|
||||
|
||||
// Add feature
|
||||
$('#addFeature').click(function() {
|
||||
const featureHtml = `
|
||||
<div class="feature-item mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="features[${featureIndex}][name]" placeholder="Название функции">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-control" name="features[${featureIndex}][included]">
|
||||
<option value="true">Включено</option>
|
||||
<option value="false">Не включено</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-feature">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#featuresContainer').append(featureHtml);
|
||||
featureIndex++;
|
||||
});
|
||||
|
||||
// Remove feature
|
||||
$(document).on('click', '.remove-feature', function() {
|
||||
$(this).closest('.feature-item').remove();
|
||||
});
|
||||
|
||||
// Form submission
|
||||
$('#serviceForm').submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const serviceId = $('#serviceId').val();
|
||||
const formData = new FormData(this);
|
||||
const data = {};
|
||||
|
||||
// Convert FormData to object
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('[') && key.includes(']')) {
|
||||
// Handle nested objects (pricing, seo, features)
|
||||
const matches = key.match(/(\w+)\[(\w+|\d+)\](?:\[(\w+)\])?/);
|
||||
if (matches) {
|
||||
const [, parent, child, grandchild] = matches;
|
||||
if (!data[parent]) data[parent] = {};
|
||||
|
||||
if (grandchild) {
|
||||
// features array handling
|
||||
if (!data[parent][child]) data[parent][child] = {};
|
||||
data[parent][child][grandchild] = value;
|
||||
} else {
|
||||
data[parent][child] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert features object to array
|
||||
if (data.features) {
|
||||
const featuresArray = [];
|
||||
Object.keys(data.features).forEach(index => {
|
||||
if (data.features[index].name) {
|
||||
featuresArray.push({
|
||||
name: data.features[index].name,
|
||||
included: data.features[index].included === 'true'
|
||||
});
|
||||
}
|
||||
});
|
||||
data.features = featuresArray;
|
||||
}
|
||||
|
||||
// Convert checkboxes
|
||||
data.isActive = $('#isActive').is(':checked');
|
||||
data.featured = $('#featured').is(':checked');
|
||||
|
||||
// Convert tags to array
|
||||
if (data.tags) {
|
||||
data.tags = data.tags.split(',').map(tag => tag.trim()).filter(tag => tag);
|
||||
}
|
||||
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
toastr.success('Услуга успешно обновлена!');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/admin/services';
|
||||
}, 1500);
|
||||
} else {
|
||||
toastr.error(result.message || 'Ошибка при обновлении услуги');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
toastr.error('Произошла ошибка при обновлении услуги');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteService() {
|
||||
const serviceId = $('#serviceId').val();
|
||||
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${serviceId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
window.location.href = '/admin/services';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
206
.history/views/admin/services/list_20251026220730.ejs
Normal file
206
.history/views/admin/services/list_20251026220730.ejs
Normal file
@@ -0,0 +1,206 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-cogs mr-2"></i>Управление услугами</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="float-sm-right">
|
||||
<a href="/admin/services/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
Добавить услугу
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Список услуг</h3>
|
||||
<div class="card-tools">
|
||||
<div class="input-group input-group-sm" style="width: 150px;">
|
||||
<input type="text" name="table_search" class="form-control float-right" placeholder="Поиск">
|
||||
<div class="input-group-append">
|
||||
<button type="submit" class="btn btn-default">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body table-responsive p-0">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<table class="table table-hover text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Название</th>
|
||||
<th>Категория</th>
|
||||
<th>Статус</th>
|
||||
<th>Цена от</th>
|
||||
<th>Время</th>
|
||||
<th>Рекомендуемая</th>
|
||||
<th>Создано</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% services.forEach(service => { %>
|
||||
<tr>
|
||||
<td>
|
||||
<small class="text-muted">#<%= service.id.slice(-8) %></small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> mr-2 text-primary"></i>
|
||||
<strong><%= service.name %></strong>
|
||||
</div>
|
||||
<% if (service.shortDescription) { %>
|
||||
<small class="text-muted d-block">
|
||||
<%= service.shortDescription.substring(0, 80) %><%= service.shortDescription.length > 80 ? '...' : '' %>
|
||||
</small>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info"><%= service.category %></span>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.isActive) { %>
|
||||
<span class="badge badge-success">Активна</span>
|
||||
<% } else { %>
|
||||
<span class="badge badge-secondary">Неактивна</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.pricing && service.pricing.basePrice) { %>
|
||||
<span class="text-success font-weight-bold">$<%= service.pricing.basePrice %></span>
|
||||
<% } else { %>
|
||||
<span class="text-muted">Не указана</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.estimatedTime) { %>
|
||||
<i class="fas fa-clock mr-1 text-info"></i>
|
||||
<%= service.estimatedTime %>
|
||||
<% } else { %>
|
||||
<span class="text-muted">-</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.featured) { %>
|
||||
<i class="fas fa-star text-warning" title="Рекомендуемая услуга"></i>
|
||||
<% } else { %>
|
||||
<i class="far fa-star text-muted"></i>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<small class="text-muted">
|
||||
<%= new Date(service.createdAt).toLocaleDateString('ru-RU') %>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="/services#<%= service.id %>" target="_blank" class="btn btn-info btn-sm" title="Посмотреть на сайте">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<a href="/admin/services/edit/<%= service.id %>" class="btn btn-warning btn-sm" title="Редактировать">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<button onclick="deleteService('<%= service.id %>')" class="btn btn-danger btn-sm" title="Удалить">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } else { %>
|
||||
<div class="p-4 text-center">
|
||||
<i class="fas fa-cogs text-muted" style="font-size: 4rem;"></i>
|
||||
<h4 class="mt-3 text-muted">Услуги не найдены</h4>
|
||||
<p class="text-muted">Добавьте первую услугу для начала работы</p>
|
||||
<a href="/admin/services/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
Добавить услугу
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<% if (pagination && pagination.total > 1) { %>
|
||||
<div class="card-footer clearfix">
|
||||
<ul class="pagination pagination-sm m-0 float-right">
|
||||
<% if (pagination.hasPrev) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current - 1 %>">«</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% for (let i = 1; i <= pagination.total; i++) { %>
|
||||
<li class="page-item <%= i === pagination.current ? 'active' : '' %>">
|
||||
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (pagination.hasNext) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current + 1 %>">»</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function deleteService(id) {
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
206
.history/views/admin/services/list_20251026220931.ejs
Normal file
206
.history/views/admin/services/list_20251026220931.ejs
Normal file
@@ -0,0 +1,206 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-cogs mr-2"></i>Управление услугами</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="float-sm-right">
|
||||
<a href="/admin/services/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
Добавить услугу
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Список услуг</h3>
|
||||
<div class="card-tools">
|
||||
<div class="input-group input-group-sm" style="width: 150px;">
|
||||
<input type="text" name="table_search" class="form-control float-right" placeholder="Поиск">
|
||||
<div class="input-group-append">
|
||||
<button type="submit" class="btn btn-default">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body table-responsive p-0">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<table class="table table-hover text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Название</th>
|
||||
<th>Категория</th>
|
||||
<th>Статус</th>
|
||||
<th>Цена от</th>
|
||||
<th>Время</th>
|
||||
<th>Рекомендуемая</th>
|
||||
<th>Создано</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% services.forEach(service => { %>
|
||||
<tr>
|
||||
<td>
|
||||
<small class="text-muted">#<%= service.id.slice(-8) %></small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> mr-2 text-primary"></i>
|
||||
<strong><%= service.name %></strong>
|
||||
</div>
|
||||
<% if (service.shortDescription) { %>
|
||||
<small class="text-muted d-block">
|
||||
<%= service.shortDescription.substring(0, 80) %><%= service.shortDescription.length > 80 ? '...' : '' %>
|
||||
</small>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-info"><%= service.category %></span>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.isActive) { %>
|
||||
<span class="badge badge-success">Активна</span>
|
||||
<% } else { %>
|
||||
<span class="badge badge-secondary">Неактивна</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.pricing && service.pricing.basePrice) { %>
|
||||
<span class="text-success font-weight-bold">$<%= service.pricing.basePrice %></span>
|
||||
<% } else { %>
|
||||
<span class="text-muted">Не указана</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.estimatedTime) { %>
|
||||
<i class="fas fa-clock mr-1 text-info"></i>
|
||||
<%= service.estimatedTime %>
|
||||
<% } else { %>
|
||||
<span class="text-muted">-</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (service.featured) { %>
|
||||
<i class="fas fa-star text-warning" title="Рекомендуемая услуга"></i>
|
||||
<% } else { %>
|
||||
<i class="far fa-star text-muted"></i>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<small class="text-muted">
|
||||
<%= new Date(service.createdAt).toLocaleDateString('ru-RU') %>
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="/services#<%= service.id %>" target="_blank" class="btn btn-info btn-sm" title="Посмотреть на сайте">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<a href="/admin/services/edit/<%= service.id %>" class="btn btn-warning btn-sm" title="Редактировать">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<button onclick="deleteService('<%= service.id %>')" class="btn btn-danger btn-sm" title="Удалить">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } else { %>
|
||||
<div class="p-4 text-center">
|
||||
<i class="fas fa-cogs text-muted" style="font-size: 4rem;"></i>
|
||||
<h4 class="mt-3 text-muted">Услуги не найдены</h4>
|
||||
<p class="text-muted">Добавьте первую услугу для начала работы</p>
|
||||
<a href="/admin/services/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus mr-1"></i>
|
||||
Добавить услугу
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<% if (pagination && pagination.total > 1) { %>
|
||||
<div class="card-footer clearfix">
|
||||
<ul class="pagination pagination-sm m-0 float-right">
|
||||
<% if (pagination.hasPrev) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current - 1 %>">«</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% for (let i = 1; i <= pagination.total; i++) { %>
|
||||
<li class="page-item <%= i === pagination.current ? 'active' : '' %>">
|
||||
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (pagination.hasNext) { %>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=<%= pagination.current + 1 %>">»</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function deleteService(id) {
|
||||
Swal.fire({
|
||||
title: 'Удалить услугу?',
|
||||
text: 'Это действие невозможно отменить!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Да, удалить!',
|
||||
cancelButtonText: 'Отмена'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch(`/api/admin/services/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire('Удалено!', 'Услуга была удалена.', 'success').then(() => {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Ошибка!', data.message || 'Ошибка при удалении услуги', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire('Ошибка!', 'Произошла ошибка при удалении услуги', 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
362
.history/views/admin/settings_20251026214908.ejs
Normal file
362
.history/views/admin/settings_20251026214908.ejs
Normal file
@@ -0,0 +1,362 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-cogs mr-2"></i>Настройки сайта</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Настройки</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Site Information Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<form id="site-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="site-title">Название сайта</label>
|
||||
<input type="text" class="form-control" id="site-title" name="siteTitle" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="site-tagline">Слоган</label>
|
||||
<input type="text" class="form-control" id="site-tagline" name="siteTagline">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="site-description">Описание сайта</label>
|
||||
<textarea class="form-control" id="site-description" name="siteDescription" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-name">Название компании</label>
|
||||
<input type="text" class="form-control" id="company-name" name="companyName" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-email">Email компании</label>
|
||||
<input type="email" class="form-control" id="company-email" name="companyEmail" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-phone">Телефон</label>
|
||||
<input type="tel" class="form-control" id="company-phone" name="companyPhone">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-address">Адрес</label>
|
||||
<input type="text" class="form-control" id="company-address" name="companyAddress">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- SEO Settings Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<form id="seo-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="meta-keywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="meta-keywords" name="metaKeywords"
|
||||
placeholder="ключевое слово 1, ключевое слово 2, ...">
|
||||
<small class="form-text text-muted">Разделяйте ключевые слова запятыми</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="meta-description">Meta Description</label>
|
||||
<textarea class="form-control" id="meta-description" name="metaDescription"
|
||||
rows="3" maxlength="160"></textarea>
|
||||
<small class="form-text text-muted">Рекомендуемая длина: до 160 символов</small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="google-analytics">Google Analytics ID</label>
|
||||
<input type="text" class="form-control" id="google-analytics" name="googleAnalytics"
|
||||
placeholder="G-XXXXXXXXXX">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="google-tag-manager">Google Tag Manager ID</label>
|
||||
<input type="text" class="form-control" id="google-tag-manager" name="googleTagManager"
|
||||
placeholder="GTM-XXXXXXX">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить SEO
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Social Media Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Социальные сети</h3>
|
||||
</div>
|
||||
<form id="social-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="facebook-url"><i class="fab fa-facebook mr-1"></i>Facebook</label>
|
||||
<input type="url" class="form-control" id="facebook-url" name="facebookUrl"
|
||||
placeholder="https://facebook.com/your-page">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="twitter-url"><i class="fab fa-twitter mr-1"></i>Twitter</label>
|
||||
<input type="url" class="form-control" id="twitter-url" name="twitterUrl"
|
||||
placeholder="https://twitter.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="linkedin-url"><i class="fab fa-linkedin mr-1"></i>LinkedIn</label>
|
||||
<input type="url" class="form-control" id="linkedin-url" name="linkedinUrl"
|
||||
placeholder="https://linkedin.com/company/your-company">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="instagram-url"><i class="fab fa-instagram mr-1"></i>Instagram</label>
|
||||
<input type="url" class="form-control" id="instagram-url" name="instagramUrl"
|
||||
placeholder="https://instagram.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="youtube-url"><i class="fab fa-youtube mr-1"></i>YouTube</label>
|
||||
<input type="url" class="form-control" id="youtube-url" name="youtubeUrl"
|
||||
placeholder="https://youtube.com/channel/your-channel">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="github-url"><i class="fab fa-github mr-1"></i>GitHub</label>
|
||||
<input type="url" class="form-control" id="github-url" name="githubUrl"
|
||||
placeholder="https://github.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить соцсети
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Maintenance Mode Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Режим обслуживания</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="maintenance-mode">
|
||||
<label class="custom-control-label" for="maintenance-mode">
|
||||
Включить режим обслуживания
|
||||
</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
В режиме обслуживания сайт будет недоступен для обычных пользователей
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="maintenance-message">Сообщение для пользователей</label>
|
||||
<textarea class="form-control" id="maintenance-message" rows="3"
|
||||
placeholder="Сайт временно недоступен из-за технических работ..."></textarea>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-warning" onclick="toggleMaintenanceMode()">
|
||||
<i class="fas fa-tools mr-1"></i>Применить настройки
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadSettings();
|
||||
|
||||
// Setup form submissions
|
||||
document.getElementById('site-settings-form').addEventListener('submit', saveSiteSettings);
|
||||
document.getElementById('seo-settings-form').addEventListener('submit', saveSeoSettings);
|
||||
document.getElementById('social-settings-form').addEventListener('submit', saveSocialSettings);
|
||||
});
|
||||
|
||||
async function loadSettings() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/settings');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
const settings = data.settings;
|
||||
|
||||
// Site settings
|
||||
document.getElementById('site-title').value = settings.siteTitle || '';
|
||||
document.getElementById('site-tagline').value = settings.siteTagline || '';
|
||||
document.getElementById('site-description').value = settings.siteDescription || '';
|
||||
document.getElementById('company-name').value = settings.companyName || '';
|
||||
document.getElementById('company-email').value = settings.companyEmail || '';
|
||||
document.getElementById('company-phone').value = settings.companyPhone || '';
|
||||
document.getElementById('company-address').value = settings.companyAddress || '';
|
||||
|
||||
// SEO settings
|
||||
document.getElementById('meta-keywords').value = settings.metaKeywords || '';
|
||||
document.getElementById('meta-description').value = settings.metaDescription || '';
|
||||
document.getElementById('google-analytics').value = settings.googleAnalytics || '';
|
||||
document.getElementById('google-tag-manager').value = settings.googleTagManager || '';
|
||||
|
||||
// Social media
|
||||
document.getElementById('facebook-url').value = settings.facebookUrl || '';
|
||||
document.getElementById('twitter-url').value = settings.twitterUrl || '';
|
||||
document.getElementById('linkedin-url').value = settings.linkedinUrl || '';
|
||||
document.getElementById('instagram-url').value = settings.instagramUrl || '';
|
||||
document.getElementById('youtube-url').value = settings.youtubeUrl || '';
|
||||
document.getElementById('github-url').value = settings.githubUrl || '';
|
||||
|
||||
// Maintenance mode
|
||||
document.getElementById('maintenance-mode').checked = settings.maintenanceMode || false;
|
||||
document.getElementById('maintenance-message').value = settings.maintenanceMessage || '';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading settings:', error);
|
||||
alert('Ошибка загрузки настроек: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSiteSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
siteTitle: formData.get('siteTitle'),
|
||||
siteTagline: formData.get('siteTagline'),
|
||||
siteDescription: formData.get('siteDescription'),
|
||||
companyName: formData.get('companyName'),
|
||||
companyEmail: formData.get('companyEmail'),
|
||||
companyPhone: formData.get('companyPhone'),
|
||||
companyAddress: formData.get('companyAddress')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'Основные настройки сохранены');
|
||||
}
|
||||
|
||||
async function saveSeoSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
metaKeywords: formData.get('metaKeywords'),
|
||||
metaDescription: formData.get('metaDescription'),
|
||||
googleAnalytics: formData.get('googleAnalytics'),
|
||||
googleTagManager: formData.get('googleTagManager')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'SEO настройки сохранены');
|
||||
}
|
||||
|
||||
async function saveSocialSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
facebookUrl: formData.get('facebookUrl'),
|
||||
twitterUrl: formData.get('twitterUrl'),
|
||||
linkedinUrl: formData.get('linkedinUrl'),
|
||||
instagramUrl: formData.get('instagramUrl'),
|
||||
youtubeUrl: formData.get('youtubeUrl'),
|
||||
githubUrl: formData.get('githubUrl')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'Настройки соцсетей сохранены');
|
||||
}
|
||||
|
||||
async function saveSettings(settings, successMessage) {
|
||||
try {
|
||||
const response = await fetch('/api/admin/settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(settings)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
alert(successMessage);
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving settings:', error);
|
||||
alert('Ошибка сохранения настроек: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleMaintenanceMode() {
|
||||
const isEnabled = document.getElementById('maintenance-mode').checked;
|
||||
const message = document.getElementById('maintenance-message').value;
|
||||
|
||||
const settings = {
|
||||
maintenanceMode: isEnabled,
|
||||
maintenanceMessage: message
|
||||
};
|
||||
|
||||
await saveSettings(settings,
|
||||
isEnabled ? 'Режим обслуживания включен' : 'Режим обслуживания отключен'
|
||||
);
|
||||
}
|
||||
</script>
|
||||
362
.history/views/admin/settings_20251026214910.ejs
Normal file
362
.history/views/admin/settings_20251026214910.ejs
Normal file
@@ -0,0 +1,362 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fas fa-cogs mr-2"></i>Настройки сайта</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Настройки</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Site Information Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Основная информация</h3>
|
||||
</div>
|
||||
<form id="site-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="site-title">Название сайта</label>
|
||||
<input type="text" class="form-control" id="site-title" name="siteTitle" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="site-tagline">Слоган</label>
|
||||
<input type="text" class="form-control" id="site-tagline" name="siteTagline">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="site-description">Описание сайта</label>
|
||||
<textarea class="form-control" id="site-description" name="siteDescription" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-name">Название компании</label>
|
||||
<input type="text" class="form-control" id="company-name" name="companyName" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-email">Email компании</label>
|
||||
<input type="email" class="form-control" id="company-email" name="companyEmail" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-phone">Телефон</label>
|
||||
<input type="tel" class="form-control" id="company-phone" name="companyPhone">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="company-address">Адрес</label>
|
||||
<input type="text" class="form-control" id="company-address" name="companyAddress">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- SEO Settings Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">SEO настройки</h3>
|
||||
</div>
|
||||
<form id="seo-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="meta-keywords">Ключевые слова</label>
|
||||
<input type="text" class="form-control" id="meta-keywords" name="metaKeywords"
|
||||
placeholder="ключевое слово 1, ключевое слово 2, ...">
|
||||
<small class="form-text text-muted">Разделяйте ключевые слова запятыми</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="meta-description">Meta Description</label>
|
||||
<textarea class="form-control" id="meta-description" name="metaDescription"
|
||||
rows="3" maxlength="160"></textarea>
|
||||
<small class="form-text text-muted">Рекомендуемая длина: до 160 символов</small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="google-analytics">Google Analytics ID</label>
|
||||
<input type="text" class="form-control" id="google-analytics" name="googleAnalytics"
|
||||
placeholder="G-XXXXXXXXXX">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="google-tag-manager">Google Tag Manager ID</label>
|
||||
<input type="text" class="form-control" id="google-tag-manager" name="googleTagManager"
|
||||
placeholder="GTM-XXXXXXX">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить SEO
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Social Media Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Социальные сети</h3>
|
||||
</div>
|
||||
<form id="social-settings-form">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="facebook-url"><i class="fab fa-facebook mr-1"></i>Facebook</label>
|
||||
<input type="url" class="form-control" id="facebook-url" name="facebookUrl"
|
||||
placeholder="https://facebook.com/your-page">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="twitter-url"><i class="fab fa-twitter mr-1"></i>Twitter</label>
|
||||
<input type="url" class="form-control" id="twitter-url" name="twitterUrl"
|
||||
placeholder="https://twitter.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="linkedin-url"><i class="fab fa-linkedin mr-1"></i>LinkedIn</label>
|
||||
<input type="url" class="form-control" id="linkedin-url" name="linkedinUrl"
|
||||
placeholder="https://linkedin.com/company/your-company">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="instagram-url"><i class="fab fa-instagram mr-1"></i>Instagram</label>
|
||||
<input type="url" class="form-control" id="instagram-url" name="instagramUrl"
|
||||
placeholder="https://instagram.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="youtube-url"><i class="fab fa-youtube mr-1"></i>YouTube</label>
|
||||
<input type="url" class="form-control" id="youtube-url" name="youtubeUrl"
|
||||
placeholder="https://youtube.com/channel/your-channel">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="github-url"><i class="fab fa-github mr-1"></i>GitHub</label>
|
||||
<input type="url" class="form-control" id="github-url" name="githubUrl"
|
||||
placeholder="https://github.com/your-account">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить соцсети
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Maintenance Mode Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Режим обслуживания</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="maintenance-mode">
|
||||
<label class="custom-control-label" for="maintenance-mode">
|
||||
Включить режим обслуживания
|
||||
</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
В режиме обслуживания сайт будет недоступен для обычных пользователей
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="maintenance-message">Сообщение для пользователей</label>
|
||||
<textarea class="form-control" id="maintenance-message" rows="3"
|
||||
placeholder="Сайт временно недоступен из-за технических работ..."></textarea>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-warning" onclick="toggleMaintenanceMode()">
|
||||
<i class="fas fa-tools mr-1"></i>Применить настройки
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadSettings();
|
||||
|
||||
// Setup form submissions
|
||||
document.getElementById('site-settings-form').addEventListener('submit', saveSiteSettings);
|
||||
document.getElementById('seo-settings-form').addEventListener('submit', saveSeoSettings);
|
||||
document.getElementById('social-settings-form').addEventListener('submit', saveSocialSettings);
|
||||
});
|
||||
|
||||
async function loadSettings() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/settings');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
const settings = data.settings;
|
||||
|
||||
// Site settings
|
||||
document.getElementById('site-title').value = settings.siteTitle || '';
|
||||
document.getElementById('site-tagline').value = settings.siteTagline || '';
|
||||
document.getElementById('site-description').value = settings.siteDescription || '';
|
||||
document.getElementById('company-name').value = settings.companyName || '';
|
||||
document.getElementById('company-email').value = settings.companyEmail || '';
|
||||
document.getElementById('company-phone').value = settings.companyPhone || '';
|
||||
document.getElementById('company-address').value = settings.companyAddress || '';
|
||||
|
||||
// SEO settings
|
||||
document.getElementById('meta-keywords').value = settings.metaKeywords || '';
|
||||
document.getElementById('meta-description').value = settings.metaDescription || '';
|
||||
document.getElementById('google-analytics').value = settings.googleAnalytics || '';
|
||||
document.getElementById('google-tag-manager').value = settings.googleTagManager || '';
|
||||
|
||||
// Social media
|
||||
document.getElementById('facebook-url').value = settings.facebookUrl || '';
|
||||
document.getElementById('twitter-url').value = settings.twitterUrl || '';
|
||||
document.getElementById('linkedin-url').value = settings.linkedinUrl || '';
|
||||
document.getElementById('instagram-url').value = settings.instagramUrl || '';
|
||||
document.getElementById('youtube-url').value = settings.youtubeUrl || '';
|
||||
document.getElementById('github-url').value = settings.githubUrl || '';
|
||||
|
||||
// Maintenance mode
|
||||
document.getElementById('maintenance-mode').checked = settings.maintenanceMode || false;
|
||||
document.getElementById('maintenance-message').value = settings.maintenanceMessage || '';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading settings:', error);
|
||||
alert('Ошибка загрузки настроек: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSiteSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
siteTitle: formData.get('siteTitle'),
|
||||
siteTagline: formData.get('siteTagline'),
|
||||
siteDescription: formData.get('siteDescription'),
|
||||
companyName: formData.get('companyName'),
|
||||
companyEmail: formData.get('companyEmail'),
|
||||
companyPhone: formData.get('companyPhone'),
|
||||
companyAddress: formData.get('companyAddress')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'Основные настройки сохранены');
|
||||
}
|
||||
|
||||
async function saveSeoSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
metaKeywords: formData.get('metaKeywords'),
|
||||
metaDescription: formData.get('metaDescription'),
|
||||
googleAnalytics: formData.get('googleAnalytics'),
|
||||
googleTagManager: formData.get('googleTagManager')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'SEO настройки сохранены');
|
||||
}
|
||||
|
||||
async function saveSocialSettings(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const settings = {
|
||||
facebookUrl: formData.get('facebookUrl'),
|
||||
twitterUrl: formData.get('twitterUrl'),
|
||||
linkedinUrl: formData.get('linkedinUrl'),
|
||||
instagramUrl: formData.get('instagramUrl'),
|
||||
youtubeUrl: formData.get('youtubeUrl'),
|
||||
githubUrl: formData.get('githubUrl')
|
||||
};
|
||||
|
||||
await saveSettings(settings, 'Настройки соцсетей сохранены');
|
||||
}
|
||||
|
||||
async function saveSettings(settings, successMessage) {
|
||||
try {
|
||||
const response = await fetch('/api/admin/settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(settings)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
alert(successMessage);
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving settings:', error);
|
||||
alert('Ошибка сохранения настроек: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleMaintenanceMode() {
|
||||
const isEnabled = document.getElementById('maintenance-mode').checked;
|
||||
const message = document.getElementById('maintenance-message').value;
|
||||
|
||||
const settings = {
|
||||
maintenanceMode: isEnabled,
|
||||
maintenanceMessage: message
|
||||
};
|
||||
|
||||
await saveSettings(settings,
|
||||
isEnabled ? 'Режим обслуживания включен' : 'Режим обслуживания отключен'
|
||||
);
|
||||
}
|
||||
</script>
|
||||
1281
.history/views/admin/telegram_20251026214715.ejs
Normal file
1281
.history/views/admin/telegram_20251026214715.ejs
Normal file
File diff suppressed because it is too large
Load Diff
360
.history/views/admin/telegram_20251026214810.ejs
Normal file
360
.history/views/admin/telegram_20251026214810.ejs
Normal file
@@ -0,0 +1,360 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fab fa-telegram mr-2 text-info"></i>Telegram Bot</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Telegram Bot</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Bot Status Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Статус бота</h3>
|
||||
<div class="card-tools">
|
||||
<button id="refresh-status" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" id="status-icon">
|
||||
<i class="fas fa-question"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">Статус подключения</span>
|
||||
<span class="info-box-number" id="status-text">Проверка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info">
|
||||
<i class="fab fa-telegram"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">Имя бота</span>
|
||||
<span class="info-box-number" id="bot-name">Загрузка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Конфигурация</h3>
|
||||
</div>
|
||||
<form id="config-form">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="bot-token">Токен бота</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control" id="bot-token" name="botToken" placeholder="Введите токен бота">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="toggleTokenVisibility()">
|
||||
<i class="fas fa-eye" id="token-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
Получите токен у <a href="https://t.me/BotFather" target="_blank">@BotFather</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="admin-chat-id">ID чата администратора</label>
|
||||
<input type="text" class="form-control" id="admin-chat-id" name="adminChatId" placeholder="Введите ID чата">
|
||||
<small class="form-text text-muted">
|
||||
Узнайте ваш ID чата у <a href="https://t.me/userinfobot" target="_blank">@userinfobot</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="notifications-enabled" name="notificationsEnabled">
|
||||
<label class="custom-control-label" for="notifications-enabled">Включить уведомления</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Типы уведомлений</label>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-contacts" name="notifyContacts">
|
||||
<label class="custom-control-label" for="notify-contacts">Новые контакты</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-orders" name="notifyOrders">
|
||||
<label class="custom-control-label" for="notify-orders">Новые заказы</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-errors" name="notifyErrors">
|
||||
<label class="custom-control-label" for="notify-errors">Системные ошибки</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-updates" name="notifyUpdates">
|
||||
<label class="custom-control-label" for="notify-updates">Обновления системы</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary ml-2" onclick="testConnection()">
|
||||
<i class="fas fa-bolt mr-1"></i>Проверить подключение
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Test Message Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Тестовое сообщение</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="test-message">Сообщение</label>
|
||||
<textarea class="form-control" id="test-message" rows="3" placeholder="Введите тестовое сообщение...">Тестовое сообщение от SmartSolTech Admin Panel</textarea>
|
||||
</div>
|
||||
<button type="button" class="btn btn-info" onclick="sendTestMessage()">
|
||||
<i class="fas fa-paper-plane mr-1"></i>Отправить тест
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Activity Log Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Журнал активности</h3>
|
||||
<div class="card-tools">
|
||||
<button class="btn btn-sm btn-default" onclick="clearLog()">
|
||||
<i class="fas fa-trash"></i> Очистить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="activity-log" style="max-height: 300px; overflow-y: auto;">
|
||||
<!-- Log entries will be added here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
let activityLog = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadConfig();
|
||||
checkBotStatus();
|
||||
initializeLog();
|
||||
|
||||
document.getElementById('config-form').addEventListener('submit', saveConfig);
|
||||
});
|
||||
|
||||
function addLog(message, type = 'info') {
|
||||
const timestamp = new Date().toLocaleString('ru-RU');
|
||||
const logEntry = { timestamp, message, type };
|
||||
|
||||
activityLog.unshift(logEntry);
|
||||
if (activityLog.length > 100) {
|
||||
activityLog = activityLog.slice(0, 100);
|
||||
}
|
||||
|
||||
updateLogDisplay();
|
||||
}
|
||||
|
||||
function updateLogDisplay() {
|
||||
const logContainer = document.getElementById('activity-log');
|
||||
const typeColors = {
|
||||
info: 'text-info',
|
||||
success: 'text-success',
|
||||
error: 'text-danger',
|
||||
warning: 'text-warning'
|
||||
};
|
||||
|
||||
logContainer.innerHTML = activityLog.map(entry => `
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">[${entry.timestamp}]</small>
|
||||
<span class="${typeColors[entry.type] || 'text-info'}">${entry.message}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function initializeLog() {
|
||||
addLog('Telegram Bot панель загружена');
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
if (confirm('Очистить журнал активности?')) {
|
||||
activityLog = [];
|
||||
updateLogDisplay();
|
||||
addLog('Журнал активности очищен');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadConfig() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/config');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
const config = data.config;
|
||||
document.getElementById('bot-token').value = config.botToken || '';
|
||||
document.getElementById('admin-chat-id').value = config.adminChatId || '';
|
||||
document.getElementById('notifications-enabled').checked = config.notificationsEnabled || false;
|
||||
document.getElementById('notify-contacts').checked = config.notifyContacts || false;
|
||||
document.getElementById('notify-orders').checked = config.notifyOrders || false;
|
||||
document.getElementById('notify-errors').checked = config.notifyErrors || false;
|
||||
document.getElementById('notify-updates').checked = config.notifyUpdates || false;
|
||||
|
||||
addLog('Конфигурация загружена');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading config:', error);
|
||||
addLog('Ошибка загрузки конфигурации: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveConfig(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const config = {
|
||||
botToken: formData.get('botToken'),
|
||||
adminChatId: formData.get('adminChatId'),
|
||||
notificationsEnabled: formData.has('notificationsEnabled'),
|
||||
notifyContacts: formData.has('notifyContacts'),
|
||||
notifyOrders: formData.has('notifyOrders'),
|
||||
notifyErrors: formData.has('notifyErrors'),
|
||||
notifyUpdates: formData.has('notifyUpdates')
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/config', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(config)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
addLog('Конфигурация сохранена', 'success');
|
||||
setTimeout(checkBotStatus, 1000);
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving config:', error);
|
||||
addLog('Ошибка сохранения конфигурации: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkBotStatus() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/status');
|
||||
const data = await response.json();
|
||||
|
||||
const statusIcon = document.getElementById('status-icon');
|
||||
const statusText = document.getElementById('status-text');
|
||||
const botName = document.getElementById('bot-name');
|
||||
|
||||
if (data.success && data.status.connected) {
|
||||
statusIcon.className = 'info-box-icon bg-success';
|
||||
statusIcon.innerHTML = '<i class="fas fa-check"></i>';
|
||||
statusText.textContent = 'Подключен';
|
||||
botName.textContent = data.status.botInfo.first_name;
|
||||
addLog('Бот подключен: ' + data.status.botInfo.first_name, 'success');
|
||||
} else {
|
||||
statusIcon.className = 'info-box-icon bg-danger';
|
||||
statusIcon.innerHTML = '<i class="fas fa-times"></i>';
|
||||
statusText.textContent = 'Не подключен';
|
||||
botName.textContent = 'Не подключен';
|
||||
addLog('Бот не подключен: ' + (data.message || 'Неизвестная ошибка'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking bot status:', error);
|
||||
const statusIcon = document.getElementById('status-icon');
|
||||
const statusText = document.getElementById('status-text');
|
||||
const botName = document.getElementById('bot-name');
|
||||
|
||||
statusIcon.className = 'info-box-icon bg-warning';
|
||||
statusIcon.innerHTML = '<i class="fas fa-exclamation"></i>';
|
||||
statusText.textContent = 'Ошибка проверки';
|
||||
botName.textContent = 'Ошибка';
|
||||
addLog('Ошибка проверки статуса: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function testConnection() {
|
||||
addLog('Проверка подключения...');
|
||||
await checkBotStatus();
|
||||
}
|
||||
|
||||
async function sendTestMessage() {
|
||||
const message = document.getElementById('test-message').value;
|
||||
if (!message.trim()) {
|
||||
alert('Введите сообщение для отправки');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
addLog('Отправка тестового сообщения...');
|
||||
|
||||
const response = await fetch('/api/admin/telegram/test', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ message })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
addLog('Тестовое сообщение отправлено', 'success');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error sending test message:', error);
|
||||
addLog('Ошибка отправки сообщения: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTokenVisibility() {
|
||||
const tokenInput = document.getElementById('bot-token');
|
||||
const tokenEye = document.getElementById('token-eye');
|
||||
|
||||
if (tokenInput.type === 'password') {
|
||||
tokenInput.type = 'text';
|
||||
tokenEye.className = 'fas fa-eye-slash';
|
||||
} else {
|
||||
tokenInput.type = 'password';
|
||||
tokenEye.className = 'fas fa-eye';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
360
.history/views/admin/telegram_20251026214811.ejs
Normal file
360
.history/views/admin/telegram_20251026214811.ejs
Normal file
@@ -0,0 +1,360 @@
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1><i class="fab fa-telegram mr-2 text-info"></i>Telegram Bot</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="/admin">Админ</a></li>
|
||||
<li class="breadcrumb-item active">Telegram Bot</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<!-- Bot Status Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Статус бота</h3>
|
||||
<div class="card-tools">
|
||||
<button id="refresh-status" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon" id="status-icon">
|
||||
<i class="fas fa-question"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">Статус подключения</span>
|
||||
<span class="info-box-number" id="status-text">Проверка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-info">
|
||||
<i class="fab fa-telegram"></i>
|
||||
</span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">Имя бота</span>
|
||||
<span class="info-box-number" id="bot-name">Загрузка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Конфигурация</h3>
|
||||
</div>
|
||||
<form id="config-form">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="bot-token">Токен бота</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control" id="bot-token" name="botToken" placeholder="Введите токен бота">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="toggleTokenVisibility()">
|
||||
<i class="fas fa-eye" id="token-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
Получите токен у <a href="https://t.me/BotFather" target="_blank">@BotFather</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="admin-chat-id">ID чата администратора</label>
|
||||
<input type="text" class="form-control" id="admin-chat-id" name="adminChatId" placeholder="Введите ID чата">
|
||||
<small class="form-text text-muted">
|
||||
Узнайте ваш ID чата у <a href="https://t.me/userinfobot" target="_blank">@userinfobot</a>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="notifications-enabled" name="notificationsEnabled">
|
||||
<label class="custom-control-label" for="notifications-enabled">Включить уведомления</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Типы уведомлений</label>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-contacts" name="notifyContacts">
|
||||
<label class="custom-control-label" for="notify-contacts">Новые контакты</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-orders" name="notifyOrders">
|
||||
<label class="custom-control-label" for="notify-orders">Новые заказы</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-errors" name="notifyErrors">
|
||||
<label class="custom-control-label" for="notify-errors">Системные ошибки</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="notify-updates" name="notifyUpdates">
|
||||
<label class="custom-control-label" for="notify-updates">Обновления системы</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save mr-1"></i>Сохранить
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary ml-2" onclick="testConnection()">
|
||||
<i class="fas fa-bolt mr-1"></i>Проверить подключение
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Test Message Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Тестовое сообщение</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="test-message">Сообщение</label>
|
||||
<textarea class="form-control" id="test-message" rows="3" placeholder="Введите тестовое сообщение...">Тестовое сообщение от SmartSolTech Admin Panel</textarea>
|
||||
</div>
|
||||
<button type="button" class="btn btn-info" onclick="sendTestMessage()">
|
||||
<i class="fas fa-paper-plane mr-1"></i>Отправить тест
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Activity Log Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Журнал активности</h3>
|
||||
<div class="card-tools">
|
||||
<button class="btn btn-sm btn-default" onclick="clearLog()">
|
||||
<i class="fas fa-trash"></i> Очистить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="activity-log" style="max-height: 300px; overflow-y: auto;">
|
||||
<!-- Log entries will be added here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
let activityLog = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadConfig();
|
||||
checkBotStatus();
|
||||
initializeLog();
|
||||
|
||||
document.getElementById('config-form').addEventListener('submit', saveConfig);
|
||||
});
|
||||
|
||||
function addLog(message, type = 'info') {
|
||||
const timestamp = new Date().toLocaleString('ru-RU');
|
||||
const logEntry = { timestamp, message, type };
|
||||
|
||||
activityLog.unshift(logEntry);
|
||||
if (activityLog.length > 100) {
|
||||
activityLog = activityLog.slice(0, 100);
|
||||
}
|
||||
|
||||
updateLogDisplay();
|
||||
}
|
||||
|
||||
function updateLogDisplay() {
|
||||
const logContainer = document.getElementById('activity-log');
|
||||
const typeColors = {
|
||||
info: 'text-info',
|
||||
success: 'text-success',
|
||||
error: 'text-danger',
|
||||
warning: 'text-warning'
|
||||
};
|
||||
|
||||
logContainer.innerHTML = activityLog.map(entry => `
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">[${entry.timestamp}]</small>
|
||||
<span class="${typeColors[entry.type] || 'text-info'}">${entry.message}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function initializeLog() {
|
||||
addLog('Telegram Bot панель загружена');
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
if (confirm('Очистить журнал активности?')) {
|
||||
activityLog = [];
|
||||
updateLogDisplay();
|
||||
addLog('Журнал активности очищен');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadConfig() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/config');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
const config = data.config;
|
||||
document.getElementById('bot-token').value = config.botToken || '';
|
||||
document.getElementById('admin-chat-id').value = config.adminChatId || '';
|
||||
document.getElementById('notifications-enabled').checked = config.notificationsEnabled || false;
|
||||
document.getElementById('notify-contacts').checked = config.notifyContacts || false;
|
||||
document.getElementById('notify-orders').checked = config.notifyOrders || false;
|
||||
document.getElementById('notify-errors').checked = config.notifyErrors || false;
|
||||
document.getElementById('notify-updates').checked = config.notifyUpdates || false;
|
||||
|
||||
addLog('Конфигурация загружена');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading config:', error);
|
||||
addLog('Ошибка загрузки конфигурации: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveConfig(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
const config = {
|
||||
botToken: formData.get('botToken'),
|
||||
adminChatId: formData.get('adminChatId'),
|
||||
notificationsEnabled: formData.has('notificationsEnabled'),
|
||||
notifyContacts: formData.has('notifyContacts'),
|
||||
notifyOrders: formData.has('notifyOrders'),
|
||||
notifyErrors: formData.has('notifyErrors'),
|
||||
notifyUpdates: formData.has('notifyUpdates')
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/config', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(config)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
addLog('Конфигурация сохранена', 'success');
|
||||
setTimeout(checkBotStatus, 1000);
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving config:', error);
|
||||
addLog('Ошибка сохранения конфигурации: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkBotStatus() {
|
||||
try {
|
||||
const response = await fetch('/api/admin/telegram/status');
|
||||
const data = await response.json();
|
||||
|
||||
const statusIcon = document.getElementById('status-icon');
|
||||
const statusText = document.getElementById('status-text');
|
||||
const botName = document.getElementById('bot-name');
|
||||
|
||||
if (data.success && data.status.connected) {
|
||||
statusIcon.className = 'info-box-icon bg-success';
|
||||
statusIcon.innerHTML = '<i class="fas fa-check"></i>';
|
||||
statusText.textContent = 'Подключен';
|
||||
botName.textContent = data.status.botInfo.first_name;
|
||||
addLog('Бот подключен: ' + data.status.botInfo.first_name, 'success');
|
||||
} else {
|
||||
statusIcon.className = 'info-box-icon bg-danger';
|
||||
statusIcon.innerHTML = '<i class="fas fa-times"></i>';
|
||||
statusText.textContent = 'Не подключен';
|
||||
botName.textContent = 'Не подключен';
|
||||
addLog('Бот не подключен: ' + (data.message || 'Неизвестная ошибка'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking bot status:', error);
|
||||
const statusIcon = document.getElementById('status-icon');
|
||||
const statusText = document.getElementById('status-text');
|
||||
const botName = document.getElementById('bot-name');
|
||||
|
||||
statusIcon.className = 'info-box-icon bg-warning';
|
||||
statusIcon.innerHTML = '<i class="fas fa-exclamation"></i>';
|
||||
statusText.textContent = 'Ошибка проверки';
|
||||
botName.textContent = 'Ошибка';
|
||||
addLog('Ошибка проверки статуса: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function testConnection() {
|
||||
addLog('Проверка подключения...');
|
||||
await checkBotStatus();
|
||||
}
|
||||
|
||||
async function sendTestMessage() {
|
||||
const message = document.getElementById('test-message').value;
|
||||
if (!message.trim()) {
|
||||
alert('Введите сообщение для отправки');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
addLog('Отправка тестового сообщения...');
|
||||
|
||||
const response = await fetch('/api/admin/telegram/test', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ message })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
addLog('Тестовое сообщение отправлено', 'success');
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error sending test message:', error);
|
||||
addLog('Ошибка отправки сообщения: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTokenVisibility() {
|
||||
const tokenInput = document.getElementById('bot-token');
|
||||
const tokenEye = document.getElementById('token-eye');
|
||||
|
||||
if (tokenInput.type === 'password') {
|
||||
tokenInput.type = 'text';
|
||||
tokenEye.className = 'fas fa-eye-slash';
|
||||
} else {
|
||||
tokenInput.type = 'password';
|
||||
tokenEye.className = 'fas fa-eye';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
316
.history/views/index_20251026203540.ejs
Normal file
316
.history/views/index_20251026203540.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-10 left-2/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
316
.history/views/index_20251026203548.ejs
Normal file
316
.history/views/index_20251026203548.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-10 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
316
.history/views/index_20251026203551.ejs
Normal file
316
.history/views/index_20251026203551.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-10 left-1/2 -translate-x-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
316
.history/views/index_20251026203600.ejs
Normal file
316
.history/views/index_20251026203600.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-10 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
316
.history/views/index_20251026203612.ejs
Normal file
316
.history/views/index_20251026203612.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-20 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
316
.history/views/index_20251026203617.ejs
Normal file
316
.history/views/index_20251026203617.ejs
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-gray-300 dark:text-gray-200 mb-8 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="btn-primary bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-4 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('hero.cta.start') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-4 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator -->
|
||||
<div class="absolute bottom-20 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
353
.history/views/index_20251026210549.ejs
Normal file
353
.history/views/index_20251026210549.ejs
Normal file
@@ -0,0 +1,353 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('services.title.our') %> <span class="text-blue-600 dark:text-blue-400"><%- __('services.title.services') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Web Development Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-code text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.web.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.web.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-mobile-alt text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.mobile.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.mobile.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-palette text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.design.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.design.price') %></div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service -->
|
||||
<div class="group p-8 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-white dark:hover:bg-gray-700 hover:shadow-xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="text-blue-600 dark:text-blue-400 mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-chart-line text-4xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('services.marketing.description') %></p>
|
||||
<div class="text-blue-600 dark:text-blue-400 font-semibold"><%- __('services.marketing.price') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/services" class="inline-flex items-center px-6 py-3 border border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400 font-semibold rounded-lg hover:bg-blue-600 hover:text-white dark:hover:bg-blue-400 dark:hover:text-gray-900 transition-colors">
|
||||
<%- __('services.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
403
.history/views/index_20251026210642.ejs
Normal file
403
.history/views/index_20251026210642.ejs
Normal file
@@ -0,0 +1,403 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
403
.history/views/index_20251026210645.ejs
Normal file
403
.history/views/index_20251026210645.ejs
Normal file
@@ -0,0 +1,403 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-purple-600 dark:text-purple-400"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center max-w-3xl mx-auto">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-48 object-cover portfolio-image">
|
||||
<% } else { %>
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%= project.category %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i><%= project.viewCount || 0 %>
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%= project.title %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%= project.shortDescription || project.description %></p>
|
||||
<a href="/portfolio/<%= project._id %>" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items -->
|
||||
<div class="group bg-white dark:bg-gray-700 rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 card-hover" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item">
|
||||
<div class="w-full h-48 bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white text-2xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">React</span>
|
||||
<span class="px-2 py-1 bg-white/20 glass-effect text-white text-xs rounded-full">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 text-sm rounded-full font-medium"><%- __('portfolio.default.ecommerce') %></span>
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
<i class="fas fa-eye mr-1"></i>1,234
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('portfolio.default.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-4"><%- __('portfolio.default.description') %></p>
|
||||
<a href="#" class="inline-flex items-center text-blue-600 dark:text-blue-400 font-semibold hover:text-blue-700 dark:hover:text-blue-300 transition-colors">
|
||||
<%- __('common.view_details') %>
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12" data-aos="fade-up">
|
||||
<a href="/portfolio" class="inline-flex items-center px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white font-semibold rounded-lg hover:bg-purple-700 dark:hover:bg-purple-400 transition-colors">
|
||||
<%- __('portfolio.view_all') %>
|
||||
<svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
449
.history/views/index_20251026210819.ejs
Normal file
449
.history/views/index_20251026210819.ejs
Normal file
@@ -0,0 +1,449 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800 relative overflow-hidden">
|
||||
<!-- Background Elements -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-30"></div>
|
||||
<div class="absolute top-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
<div class="absolute bottom-20 right-10 w-72 h-72 bg-blue-500/10 rounded-full blur-3xl"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300 rounded-full text-sm font-medium mb-4">
|
||||
포트폴리오
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<!-- Project Image -->
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-full object-cover portfolio-image transition-transform duration-500 group-hover:scale-110">
|
||||
<% } else { %>
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
|
||||
<!-- Technologies Tags */
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Count Badge -->
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span><%= project.viewCount || 0 %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Info -->
|
||||
<div class="p-6">
|
||||
<!-- Category Badge -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%= project.category %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
|
||||
<!-- Project Title -->
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%= project.title %>
|
||||
</h3>
|
||||
|
||||
<!-- Project Description -->
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed line-clamp-2">
|
||||
<%= project.shortDescription || project.description %>
|
||||
</p>
|
||||
|
||||
<!-- View Details Link -->
|
||||
<a href="/portfolio/<%= project._id %>" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items with enhanced design -->
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">React</span>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>1,234</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%- __('portfolio.default.ecommerce') %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%- __('portfolio.default.title') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
|
||||
<%- __('portfolio.default.description') %>
|
||||
</p>
|
||||
<a href="#" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/portfolio" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-semibold rounded-2xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('portfolio.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
449
.history/views/index_20251026210826.ejs
Normal file
449
.history/views/index_20251026210826.ejs
Normal file
@@ -0,0 +1,449 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800 relative overflow-hidden">
|
||||
<!-- Background Elements -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-30"></div>
|
||||
<div class="absolute top-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
<div class="absolute bottom-20 right-10 w-72 h-72 bg-blue-500/10 rounded-full blur-3xl"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300 rounded-full text-sm font-medium mb-4">
|
||||
포트폴리오
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<!-- Project Image -->
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-full object-cover portfolio-image transition-transform duration-500 group-hover:scale-110">
|
||||
<% } else { %>
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
|
||||
<!-- Technologies Tags */
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Count Badge -->
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span><%= project.viewCount || 0 %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Info -->
|
||||
<div class="p-6">
|
||||
<!-- Category Badge -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%= project.category %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
|
||||
<!-- Project Title -->
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%= project.title %>
|
||||
</h3>
|
||||
|
||||
<!-- Project Description -->
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed line-clamp-2">
|
||||
<%= project.shortDescription || project.description %>
|
||||
</p>
|
||||
|
||||
<!-- View Details Link -->
|
||||
<a href="/portfolio/<%= project._id %>" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items with enhanced design -->
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">React</span>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>1,234</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%- __('portfolio.default.ecommerce') %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%- __('portfolio.default.title') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
|
||||
<%- __('portfolio.default.description') %>
|
||||
</p>
|
||||
<a href="#" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/portfolio" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-semibold rounded-2xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('portfolio.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Calculator CTA Section -->
|
||||
<section class="py-20 cta-section">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-white mb-6">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-blue-100 mb-8 max-w-3xl mx-auto">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
<a href="/calculator" class="inline-flex items-center px-8 py-4 bg-white text-blue-600 font-bold rounded-full text-lg hover:bg-gray-100 transition-colors transform hover:scale-105">
|
||||
<i class="fas fa-calculator mr-3"></i>
|
||||
<%- __('calculator.cta.button') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
500
.history/views/index_20251026210843.ejs
Normal file
500
.history/views/index_20251026210843.ejs
Normal file
@@ -0,0 +1,500 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800 relative overflow-hidden">
|
||||
<!-- Background Elements -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-30"></div>
|
||||
<div class="absolute top-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
<div class="absolute bottom-20 right-10 w-72 h-72 bg-blue-500/10 rounded-full blur-3xl"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300 rounded-full text-sm font-medium mb-4">
|
||||
포트폴리오
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<!-- Project Image -->
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-full object-cover portfolio-image transition-transform duration-500 group-hover:scale-110">
|
||||
<% } else { %>
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
|
||||
<!-- Technologies Tags */
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Count Badge -->
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span><%= project.viewCount || 0 %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Info -->
|
||||
<div class="p-6">
|
||||
<!-- Category Badge -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%= project.category %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
|
||||
<!-- Project Title -->
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%= project.title %>
|
||||
</h3>
|
||||
|
||||
<!-- Project Description -->
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed line-clamp-2">
|
||||
<%= project.shortDescription || project.description %>
|
||||
</p>
|
||||
|
||||
<!-- View Details Link -->
|
||||
<a href="/portfolio/<%= project._id %>" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items with enhanced design -->
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">React</span>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>1,234</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%- __('portfolio.default.ecommerce') %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%- __('portfolio.default.title') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
|
||||
<%- __('portfolio.default.description') %>
|
||||
</p>
|
||||
<a href="#" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/portfolio" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-semibold rounded-2xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('portfolio.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Calculator CTA Section -->
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<!-- Enhanced Background -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-indigo-700"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute top-1/4 left-1/4 w-64 h-64 bg-white/5 rounded-full animate-float blur-xl"></div>
|
||||
<div class="absolute top-3/4 right-1/4 w-48 h-48 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 2s;"></div>
|
||||
<div class="absolute top-1/2 left-3/4 w-32 h-32 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 4s;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<!-- Enhanced Icon -->
|
||||
<div class="inline-flex items-center justify-center w-20 h-20 bg-white/10 rounded-full mb-8 backdrop-blur-sm">
|
||||
<i class="fas fa-calculator text-3xl text-white"></i>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Title -->
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl text-blue-100 mb-12 max-w-4xl mx-auto leading-relaxed">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Features List -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12 max-w-4xl mx-auto">
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-bolt text-sm"></i>
|
||||
</div>
|
||||
<span>즉시 견적</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-shield-alt text-sm"></i>
|
||||
</div>
|
||||
<span>정확한 계산</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-gift text-sm"></i>
|
||||
</div>
|
||||
<span>무료 상담</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<a href="/calculator" class="group inline-flex items-center px-10 py-5 bg-white text-blue-600 font-bold rounded-2xl text-lg hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-2xl hover:shadow-white/25">
|
||||
<i class="fas fa-calculator mr-4 text-xl"></i>
|
||||
<span class="mr-4"><%- __('calculator.cta.button') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<!-- Trust Indicators -->
|
||||
<div class="mt-12 text-white/70 text-sm">
|
||||
<p>✓ 5분 안에 견적 확인 ✓ 전문가 검증 ✓ 맞춤형 솔루션</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('contact.cta.ready') %> <span class="text-blue-600 dark:text-blue-400"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
<p class="text-lg text-white text-center mb-8">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-phone text-blue-600 dark:text-blue-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fas fa-envelope text-purple-600 dark:text-purple-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mr-4">
|
||||
<i class="fab fa-telegram text-green-600 dark:text-green-400"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-gray-900 dark:text-white"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-aos="fade-left">
|
||||
<div class="contact-form p-8 rounded-2xl shadow-lg bg-white dark:bg-gray-800">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-6"><%- __('contact.form.title') %></h3>
|
||||
<form id="quick-contact-form" class="space-y-4">
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<select name="serviceInterest" class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required class="form-input w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="w-full btn-primary bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold py-3 rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('contact.form.submit') %>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
578
.history/views/index_20251026210935.ejs
Normal file
578
.history/views/index_20251026210935.ejs
Normal file
@@ -0,0 +1,578 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800 relative overflow-hidden">
|
||||
<!-- Background Elements -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-30"></div>
|
||||
<div class="absolute top-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
<div class="absolute bottom-20 right-10 w-72 h-72 bg-blue-500/10 rounded-full blur-3xl"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300 rounded-full text-sm font-medium mb-4">
|
||||
포트폴리오
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<!-- Project Image -->
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-full object-cover portfolio-image transition-transform duration-500 group-hover:scale-110">
|
||||
<% } else { %>
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
|
||||
<!-- Technologies Tags */
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Count Badge -->
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span><%= project.viewCount || 0 %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Info -->
|
||||
<div class="p-6">
|
||||
<!-- Category Badge -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%= project.category %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
|
||||
<!-- Project Title -->
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%= project.title %>
|
||||
</h3>
|
||||
|
||||
<!-- Project Description -->
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed line-clamp-2">
|
||||
<%= project.shortDescription || project.description %>
|
||||
</p>
|
||||
|
||||
<!-- View Details Link -->
|
||||
<a href="/portfolio/<%= project._id %>" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items with enhanced design -->
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">React</span>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>1,234</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%- __('portfolio.default.ecommerce') %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%- __('portfolio.default.title') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
|
||||
<%- __('portfolio.default.description') %>
|
||||
</p>
|
||||
<a href="#" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/portfolio" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-semibold rounded-2xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('portfolio.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Calculator CTA Section -->
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<!-- Enhanced Background -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-indigo-700"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute top-1/4 left-1/4 w-64 h-64 bg-white/5 rounded-full animate-float blur-xl"></div>
|
||||
<div class="absolute top-3/4 right-1/4 w-48 h-48 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 2s;"></div>
|
||||
<div class="absolute top-1/2 left-3/4 w-32 h-32 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 4s;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<!-- Enhanced Icon -->
|
||||
<div class="inline-flex items-center justify-center w-20 h-20 bg-white/10 rounded-full mb-8 backdrop-blur-sm">
|
||||
<i class="fas fa-calculator text-3xl text-white"></i>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Title -->
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl text-blue-100 mb-12 max-w-4xl mx-auto leading-relaxed">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Features List -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12 max-w-4xl mx-auto">
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-bolt text-sm"></i>
|
||||
</div>
|
||||
<span>즉시 견적</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-shield-alt text-sm"></i>
|
||||
</div>
|
||||
<span>정확한 계산</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-gift text-sm"></i>
|
||||
</div>
|
||||
<span>무료 상담</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<a href="/calculator" class="group inline-flex items-center px-10 py-5 bg-white text-blue-600 font-bold rounded-2xl text-lg hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-2xl hover:shadow-white/25">
|
||||
<i class="fas fa-calculator mr-4 text-xl"></i>
|
||||
<span class="mr-4"><%- __('calculator.cta.button') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<!-- Trust Indicators -->
|
||||
<div class="mt-12 text-white/70 text-sm">
|
||||
<p>✓ 5분 안에 견적 확인 ✓ 전문가 검증 ✓ 맞춤형 솔루션</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-20"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||
<!-- Left Side - Contact Info -->
|
||||
<div data-aos="fade-right">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-6">
|
||||
연락처
|
||||
</div>
|
||||
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-8 leading-tight">
|
||||
<%- __('contact.cta.ready') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 mb-12 leading-relaxed">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Contact Methods -->
|
||||
<div class="space-y-6">
|
||||
<!-- Phone -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-phone text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-purple-50 dark:hover:bg-purple-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-envelope text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Telegram -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-green-50 dark:hover:bg-green-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fab fa-telegram text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trust Badges -->
|
||||
<div class="mt-12 grid grid-cols-3 gap-4">
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-blue-600 dark:text-blue-400">24시간</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">응답 시간</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-green-600 dark:text-green-400">100%</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">무료 상담</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-purple-600 dark:text-purple-400">전문가</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">팀 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Side - Contact Form -->
|
||||
<div data-aos="fade-left">
|
||||
<div class="relative p-8 rounded-3xl shadow-2xl bg-white dark:bg-gray-800 border border-gray-200/50 dark:border-gray-700/50">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-blue-500/10 to-purple-500/10 rounded-full -translate-y-16 translate-x-16"></div>
|
||||
|
||||
<div class="relative">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-8 flex items-center">
|
||||
<span class="mr-3"><%- __('contact.form.title') %></span>
|
||||
<div class="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</h3>
|
||||
|
||||
<form id="quick-contact-form" class="space-y-6">
|
||||
<!-- Name Input -->
|
||||
<div class="relative">
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-user text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email Input -->
|
||||
<div class="relative">
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-envelope text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone Input -->
|
||||
<div class="relative">
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>"
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-phone text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Interest Select -->
|
||||
<div class="relative">
|
||||
<select name="serviceInterest"
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-all duration-300 hover:border-blue-300 appearance-none">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4 pointer-events-none">
|
||||
<i class="fas fa-chevron-down text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Textarea -->
|
||||
<div class="relative">
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300"></textarea>
|
||||
<div class="absolute top-4 right-4">
|
||||
<i class="fas fa-comment text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button type="submit"
|
||||
class="group w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-bold py-5 rounded-xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl">
|
||||
<span class="flex items-center justify-center">
|
||||
<i class="fas fa-paper-plane mr-3 transform group-hover:translate-x-1 transition-transform duration-200"></i>
|
||||
<%- __('contact.form.submit') %>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
578
.history/views/index_20251026210937.ejs
Normal file
578
.history/views/index_20251026210937.ejs
Normal file
@@ -0,0 +1,578 @@
|
||||
|
||||
|
||||
<!-- Hero Section - Enhanced Modern Design -->
|
||||
<section class="relative bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 dark:from-gray-900 dark:via-blue-900 dark:to-purple-900 min-h-screen flex items-center overflow-hidden hero-section">
|
||||
<div class="absolute inset-0 bg-black opacity-50 dark:opacity-70"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Enhanced Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute -top-40 -right-32 w-80 h-80 bg-purple-500 dark:bg-purple-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
|
||||
<div class="absolute -bottom-40 -left-32 w-80 h-80 bg-blue-500 dark:bg-blue-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
|
||||
<div class="absolute top-40 left-40 w-80 h-80 bg-indigo-500 dark:bg-indigo-400 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
|
||||
<div class="absolute top-20 right-20 w-60 h-60 bg-pink-500 dark:bg-pink-400 rounded-full mix-blend-multiply filter blur-xl opacity-50 animate-blob animation-delay-6000"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 w-full">
|
||||
<div class="text-center">
|
||||
<!-- Enhanced Title with Better Typography -->
|
||||
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-8 leading-tight" data-aos="fade-up">
|
||||
<%- __('hero.title.smart') %>
|
||||
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 animate-gradient-x"><%- __('hero.title.solutions') %></span>
|
||||
</h1>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl md:text-2xl lg:text-3xl text-gray-300 dark:text-gray-200 mb-12 max-w-4xl mx-auto leading-relaxed" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('hero.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced Description -->
|
||||
<p class="text-lg md:text-xl text-gray-400 dark:text-gray-300 mb-12 max-w-3xl mx-auto" data-aos="fade-up" data-aos-delay="300">
|
||||
<%- __('hero.description') %>
|
||||
</p>
|
||||
|
||||
<!-- Enhanced CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center items-center mb-16" data-aos="fade-up" data-aos-delay="400">
|
||||
<a href="/contact" class="group relative bg-gradient-to-r from-blue-500 to-purple-600 text-white px-10 py-5 rounded-full text-lg font-semibold hover:from-blue-600 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-2xl overflow-hidden">
|
||||
<span class="relative z-10 flex items-center">
|
||||
<i class="fas fa-rocket mr-3"></i>
|
||||
<%- __('hero.cta.start') %>
|
||||
</span>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
</a>
|
||||
<a href="/portfolio" class="group border-2 border-white text-white px-10 py-5 rounded-full text-lg font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105 backdrop-blur-sm bg-white/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fas fa-eye mr-3"></i>
|
||||
<%- __('hero.cta.portfolio') %>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats or Features Preview -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-8 max-w-4xl mx-auto" data-aos="fade-up" data-aos-delay="500">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">50+</div>
|
||||
<div class="text-gray-300">완료된 프로젝트</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">98%</div>
|
||||
<div class="text-gray-300">고객 만족도</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-3xl md:text-4xl font-bold text-white mb-2">24/7</div>
|
||||
<div class="text-gray-300">기술 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Scroll indicator -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
|
||||
<div class="flex flex-col items-center text-white opacity-70">
|
||||
<span class="text-sm mb-2">스크롤해서 더 보기</span>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Services Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 opacity-5">
|
||||
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0); background-size: 20px 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-4">
|
||||
<%- __('services.title.our') %> <%- __('services.title.services') %>
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
혁신적인 <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">디지털 솔루션</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('services.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Services Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
|
||||
<!-- Web Development Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-3xl hover:from-blue-100 hover:to-blue-200 dark:hover:from-blue-800/30 dark:hover:to-blue-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-blue-200/50 dark:border-blue-700/50" data-aos="fade-up">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-blue-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-code text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"><%- __('services.web.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.web.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-blue-600 dark:text-blue-400 font-bold text-lg"><%- __('services.web.price') %></div>
|
||||
<div class="w-10 h-10 bg-blue-500/10 rounded-full flex items-center justify-center group-hover:bg-blue-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-blue-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile App Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/20 dark:to-green-800/20 rounded-3xl hover:from-green-100 hover:to-green-200 dark:hover:from-green-800/30 dark:hover:to-green-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-green-200/50 dark:border-green-700/50" data-aos="fade-up" data-aos-delay="100">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-green-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-mobile-alt text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-green-600 dark:group-hover:text-green-400 transition-colors"><%- __('services.mobile.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.mobile.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-green-600 dark:text-green-400 font-bold text-lg"><%- __('services.mobile.price') %></div>
|
||||
<div class="w-10 h-10 bg-green-500/10 rounded-full flex items-center justify-center group-hover:bg-green-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-green-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI/UX Design Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-3xl hover:from-purple-100 hover:to-purple-200 dark:hover:from-purple-800/30 dark:hover:to-purple-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-purple-200/50 dark:border-purple-700/50" data-aos="fade-up" data-aos-delay="200">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-purple-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-palette text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors"><%- __('services.design.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.design.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-purple-600 dark:text-purple-400 font-bold text-lg"><%- __('services.design.price') %></div>
|
||||
<div class="w-10 h-10 bg-purple-500/10 rounded-full flex items-center justify-center group-hover:bg-purple-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-purple-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Digital Marketing Service - Enhanced -->
|
||||
<div class="group relative p-8 bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/20 dark:to-orange-800/20 rounded-3xl hover:from-orange-100 hover:to-orange-200 dark:hover:from-orange-800/30 dark:hover:to-orange-700/30 hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-orange-200/50 dark:border-orange-700/50" data-aos="fade-up" data-aos-delay="300">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-orange-500/10 rounded-full -translate-y-10 translate-x-10 group-hover:scale-150 transition-transform duration-500"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg">
|
||||
<i class="fas fa-chart-line text-2xl text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4 group-hover:text-orange-600 dark:group-hover:text-orange-400 transition-colors"><%- __('services.marketing.title') %></h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed"><%- __('services.marketing.description') %></p>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-orange-600 dark:text-orange-400 font-bold text-lg"><%- __('services.marketing.price') %></div>
|
||||
<div class="w-10 h-10 bg-orange-500/10 rounded-full flex items-center justify-center group-hover:bg-orange-500 group-hover:text-white transition-all duration-300">
|
||||
<i class="fas fa-arrow-right text-orange-500 group-hover:text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/services" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-2xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('services.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Portfolio Section -->
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800 relative overflow-hidden">
|
||||
<!-- Background Elements -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-30"></div>
|
||||
<div class="absolute top-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
<div class="absolute bottom-20 right-10 w-72 h-72 bg-blue-500/10 rounded-full blur-3xl"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="text-center mb-20" data-aos="fade-up">
|
||||
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900 text-purple-600 dark:text-purple-300 rounded-full text-sm font-medium mb-4">
|
||||
포트폴리오
|
||||
</div>
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
<%- __('portfolio.title.recent') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600"><%- __('portfolio.title.projects') %></span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
<%- __('portfolio.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||
<% if (featuredPortfolio && featuredPortfolio.length > 0) { %>
|
||||
<% featuredPortfolio.forEach((project, index) => { %>
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up" data-aos-delay="<%= index * 100 %>">
|
||||
<!-- Project Image -->
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<% if (project.images && project.images.length > 0) { %>
|
||||
<img src="<%= project.images.find(img => img.isPrimary)?.url || project.images[0].url %>"
|
||||
alt="<%= project.images.find(img => img.isPrimary)?.alt || project.title %>"
|
||||
class="w-full h-full object-cover portfolio-image transition-transform duration-500 group-hover:scale-110">
|
||||
<% } else { %>
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold"><%= project.title.charAt(0) %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
|
||||
<!-- Technologies Tags */
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<% if (project.technologies && project.technologies.length > 0) { %>
|
||||
<% project.technologies.slice(0, 3).forEach(tech => { %>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium"><%= tech %></span>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Count Badge -->
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span><%= project.viewCount || 0 %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project Info -->
|
||||
<div class="p-6">
|
||||
<!-- Category Badge -->
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%= project.category %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
|
||||
<!-- Project Title -->
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%= project.title %>
|
||||
</h3>
|
||||
|
||||
<!-- Project Description -->
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed line-clamp-2">
|
||||
<%= project.shortDescription || project.description %>
|
||||
</p>
|
||||
|
||||
<!-- View Details Link -->
|
||||
<a href="/portfolio/<%= project._id %>" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<!-- Default portfolio items with enhanced design -->
|
||||
<div class="group relative bg-white dark:bg-gray-700 rounded-3xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-500 transform hover:-translate-y-3 card-hover border border-gray-200/50 dark:border-gray-600/50" data-aos="fade-up">
|
||||
<div class="relative overflow-hidden portfolio-item h-56">
|
||||
<div class="w-full h-full bg-gradient-to-br from-blue-500 via-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<span class="text-white text-3xl font-bold">E</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-300"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4 transform translate-y-8 group-hover:translate-y-0 transition-transform duration-300 opacity-0 group-hover:opacity-100">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">React</span>
|
||||
<span class="px-3 py-1 bg-white/20 glass-effect text-white text-sm rounded-full font-medium">Node.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-4 right-4">
|
||||
<div class="flex items-center space-x-1 bg-black/30 glass-effect text-white px-3 py-1 rounded-full text-sm">
|
||||
<i class="fas fa-eye"></i>
|
||||
<span>1,234</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="px-4 py-2 bg-gradient-to-r from-purple-100 to-pink-100 dark:from-purple-900/50 dark:to-pink-900/50 text-purple-600 dark:text-purple-300 text-sm rounded-full font-medium">
|
||||
<%- __('portfolio.default.ecommerce') %>
|
||||
</span>
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors leading-tight">
|
||||
<%- __('portfolio.default.title') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
|
||||
<%- __('portfolio.default.description') %>
|
||||
</p>
|
||||
<a href="#" class="group/link inline-flex items-center text-purple-600 dark:text-purple-400 font-semibold hover:text-purple-700 dark:hover:text-purple-300 transition-colors">
|
||||
<span class="mr-2"><%- __('common.view_details') %></span>
|
||||
<svg class="w-4 h-4 transform group-hover/link:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<div class="text-center" data-aos="fade-up">
|
||||
<a href="/portfolio" class="group inline-flex items-center px-8 py-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white font-semibold rounded-2xl hover:from-purple-700 hover:to-pink-700 transition-all duration-300 transform hover:scale-105 shadow-xl hover:shadow-2xl">
|
||||
<span class="mr-3"><%- __('portfolio.view_all') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Calculator CTA Section -->
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<!-- Enhanced Background -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-indigo-700"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-purple-600/20"></div>
|
||||
|
||||
<!-- Animated Background Elements -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
<div class="absolute top-1/4 left-1/4 w-64 h-64 bg-white/5 rounded-full animate-float blur-xl"></div>
|
||||
<div class="absolute top-3/4 right-1/4 w-48 h-48 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 2s;"></div>
|
||||
<div class="absolute top-1/2 left-3/4 w-32 h-32 bg-white/5 rounded-full animate-float blur-xl" style="animation-delay: 4s;"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center relative z-10">
|
||||
<div data-aos="fade-up">
|
||||
<!-- Enhanced Icon -->
|
||||
<div class="inline-flex items-center justify-center w-20 h-20 bg-white/10 rounded-full mb-8 backdrop-blur-sm">
|
||||
<i class="fas fa-calculator text-3xl text-white"></i>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced Title -->
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-white mb-6 leading-tight">
|
||||
<%- __('calculator.cta.title') %>
|
||||
</h2>
|
||||
|
||||
<!-- Enhanced Subtitle -->
|
||||
<p class="text-xl text-blue-100 mb-12 max-w-4xl mx-auto leading-relaxed">
|
||||
<%- __('calculator.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Features List -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12 max-w-4xl mx-auto">
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-bolt text-sm"></i>
|
||||
</div>
|
||||
<span>즉시 견적</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-shield-alt text-sm"></i>
|
||||
</div>
|
||||
<span>정확한 계산</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-3 text-white/90">
|
||||
<div class="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-gift text-sm"></i>
|
||||
</div>
|
||||
<span>무료 상담</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced CTA Button -->
|
||||
<a href="/calculator" class="group inline-flex items-center px-10 py-5 bg-white text-blue-600 font-bold rounded-2xl text-lg hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-2xl hover:shadow-white/25">
|
||||
<i class="fas fa-calculator mr-4 text-xl"></i>
|
||||
<span class="mr-4"><%- __('calculator.cta.button') %></span>
|
||||
<svg class="w-5 h-5 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<!-- Trust Indicators -->
|
||||
<div class="mt-12 text-white/70 text-sm">
|
||||
<p>✓ 5분 안에 견적 확인 ✓ 전문가 검증 ✓ 맞춤형 솔루션</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Enhanced Contact Section -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background Pattern -->
|
||||
<div class="absolute inset-0 bg-pattern opacity-20"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||
<!-- Left Side - Contact Info -->
|
||||
<div data-aos="fade-right">
|
||||
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 rounded-full text-sm font-medium mb-6">
|
||||
연락처
|
||||
</div>
|
||||
|
||||
<h2 class="text-3xl md:text-5xl font-bold text-gray-900 dark:text-white mb-8 leading-tight">
|
||||
<%- __('contact.cta.ready') %> <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600"><%- __('contact.cta.start') %></span><%- __('contact.cta.question') %>
|
||||
</h2>
|
||||
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300 mb-12 leading-relaxed">
|
||||
<%- __('contact.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<!-- Contact Methods -->
|
||||
<div class="space-y-6">
|
||||
<!-- Phone -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-phone text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.phone.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.phone.number') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-purple-50 dark:hover:bg-purple-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fas fa-envelope text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.email.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.email.address') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Telegram -->
|
||||
<div class="group flex items-center p-4 bg-gray-50 dark:bg-gray-800 rounded-2xl hover:bg-green-50 dark:hover:bg-green-900/20 transition-all duration-300">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center mr-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<i class="fab fa-telegram text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900 dark:text-white text-lg"><%- __('contact.telegram.title') %></div>
|
||||
<div class="text-gray-600 dark:text-gray-300 text-lg"><%- __('contact.telegram.subtitle') %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trust Badges -->
|
||||
<div class="mt-12 grid grid-cols-3 gap-4">
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-blue-600 dark:text-blue-400">24시간</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">응답 시간</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-green-600 dark:text-green-400">100%</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">무료 상담</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-2xl font-bold text-purple-600 dark:text-purple-400">전문가</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">팀 지원</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Side - Contact Form -->
|
||||
<div data-aos="fade-left">
|
||||
<div class="relative p-8 rounded-3xl shadow-2xl bg-white dark:bg-gray-800 border border-gray-200/50 dark:border-gray-700/50">
|
||||
<!-- Background Decoration -->
|
||||
<div class="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-blue-500/10 to-purple-500/10 rounded-full -translate-y-16 translate-x-16"></div>
|
||||
|
||||
<div class="relative">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-8 flex items-center">
|
||||
<span class="mr-3"><%- __('contact.form.title') %></span>
|
||||
<div class="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
|
||||
</h3>
|
||||
|
||||
<form id="quick-contact-form" class="space-y-6">
|
||||
<!-- Name Input -->
|
||||
<div class="relative">
|
||||
<input type="text" name="name" placeholder="<%- __('contact.form.name') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-user text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email Input -->
|
||||
<div class="relative">
|
||||
<input type="email" name="email" placeholder="<%- __('contact.form.email') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-envelope text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone Input -->
|
||||
<div class="relative">
|
||||
<input type="tel" name="phone" placeholder="<%- __('contact.form.phone') %>"
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<i class="fas fa-phone text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Interest Select -->
|
||||
<div class="relative">
|
||||
<select name="serviceInterest"
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-all duration-300 hover:border-blue-300 appearance-none">
|
||||
<option value=""><%- __('contact.form.service.select') %></option>
|
||||
<option value="web-development"><%- __('contact.form.service.web') %></option>
|
||||
<option value="mobile-app"><%- __('contact.form.service.mobile') %></option>
|
||||
<option value="ui-ux-design"><%- __('contact.form.service.design') %></option>
|
||||
<option value="branding"><%- __('contact.form.service.branding') %></option>
|
||||
<option value="consulting"><%- __('contact.form.service.consulting') %></option>
|
||||
<option value="other"><%- __('contact.form.service.other') %></option>
|
||||
</select>
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-4 pointer-events-none">
|
||||
<i class="fas fa-chevron-down text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Textarea -->
|
||||
<div class="relative">
|
||||
<textarea name="message" rows="4" placeholder="<%- __('contact.form.message') %>" required
|
||||
class="w-full px-6 py-4 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none dark:bg-gray-700 dark:text-white placeholder-gray-400 transition-all duration-300 hover:border-blue-300"></textarea>
|
||||
<div class="absolute top-4 right-4">
|
||||
<i class="fas fa-comment text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button type="submit"
|
||||
class="group w-full bg-gradient-to-r from-blue-600 to-purple-600 text-white font-bold py-5 rounded-xl hover:from-blue-700 hover:to-purple-700 transition-all duration-300 transform hover:scale-[1.02] shadow-lg hover:shadow-xl">
|
||||
<span class="flex items-center justify-center">
|
||||
<i class="fas fa-paper-plane mr-3 transform group-hover:translate-x-1 transition-transform duration-200"></i>
|
||||
<%- __('contact.form.submit') %>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Initialize AOS -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof AOS !== 'undefined') {
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
easing: 'ease-in-out',
|
||||
once: true
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
103
.history/views/layout_20251026210719.ejs
Normal file
103
.history/views/layout_20251026210719.ejs
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= locale || 'ko' %>" class="<%= theme === 'dark' ? 'dark' : '' %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %></title>
|
||||
|
||||
<!-- PWA Meta Tags -->
|
||||
<meta name="theme-color" content="#1a202c">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="SmartSolTech">
|
||||
|
||||
<!-- SEO Meta Tags -->
|
||||
<meta name="description" content="<%= settings && settings.seo ? settings.seo.metaDescription : 'SmartSolTech - Innovative Technology Solutions' %>">
|
||||
<meta name="keywords" content="<%= settings && settings.seo ? settings.seo.keywords : 'web development, mobile apps, UI/UX design, Korea' %>">
|
||||
<meta name="author" content="SmartSolTech">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:title" content="<%= title %>">
|
||||
<meta property="og:description" content="<%= settings && settings.seo ? settings.seo.metaDescription : 'SmartSolTech - Innovative Technology Solutions' %>">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="<%= process.env.SITE_URL || 'https://smartsoltech.kr' %>">
|
||||
<meta property="og:image" content="<%= process.env.SITE_URL || 'https://smartsoltech.kr' %>/images/og-image.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="/images/icon-192x192.png">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<link rel="stylesheet" href="/css/tailwind.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet">
|
||||
|
||||
<!-- AOS Animation Library -->
|
||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link href="/css/base.css" rel="stylesheet">
|
||||
<link href="/css/main.css" rel="stylesheet">
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
<link href="/css/theme-toggle.css" rel="stylesheet">
|
||||
<link href="/css/sticky-price.css" rel="stylesheet">
|
||||
<link href="/css/enhanced-animations.css" rel="stylesheet">
|
||||
|
||||
|
||||
</head>
|
||||
<body class="font-sans dark:bg-gray-900 dark:text-gray-100">
|
||||
<!-- Navigation -->
|
||||
<%- include('partials/navigation') %>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
<%- body %>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<%- include('partials/footer') %>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<!-- PWA Service Worker -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then(registration => {
|
||||
console.log('SW registered: ', registration);
|
||||
})
|
||||
.catch(registrationError => {
|
||||
console.log('SW registration failed: ', registrationError);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Analytics -->
|
||||
<% if (settings && settings.seo && settings.seo.googleAnalytics) { %>
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= settings.seo.googleAnalytics %>"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '<%= settings.seo.googleAnalytics %>');
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
<!-- Page-specific scripts -->
|
||||
<%- script %>
|
||||
</body>
|
||||
</html>
|
||||
103
.history/views/layout_20251026210722.ejs
Normal file
103
.history/views/layout_20251026210722.ejs
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="<%= locale || 'ko' %>" class="<%= theme === 'dark' ? 'dark' : '' %>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%= title %></title>
|
||||
|
||||
<!-- PWA Meta Tags -->
|
||||
<meta name="theme-color" content="#1a202c">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="SmartSolTech">
|
||||
|
||||
<!-- SEO Meta Tags -->
|
||||
<meta name="description" content="<%= settings && settings.seo ? settings.seo.metaDescription : 'SmartSolTech - Innovative Technology Solutions' %>">
|
||||
<meta name="keywords" content="<%= settings && settings.seo ? settings.seo.keywords : 'web development, mobile apps, UI/UX design, Korea' %>">
|
||||
<meta name="author" content="SmartSolTech">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:title" content="<%= title %>">
|
||||
<meta property="og:description" content="<%= settings && settings.seo ? settings.seo.metaDescription : 'SmartSolTech - Innovative Technology Solutions' %>">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="<%= process.env.SITE_URL || 'https://smartsoltech.kr' %>">
|
||||
<meta property="og:image" content="<%= process.env.SITE_URL || 'https://smartsoltech.kr' %>/images/og-image.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="/images/icon-192x192.png">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<link rel="stylesheet" href="/css/tailwind.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet">
|
||||
|
||||
<!-- AOS Animation Library -->
|
||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link href="/css/base.css" rel="stylesheet">
|
||||
<link href="/css/main.css" rel="stylesheet">
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
<link href="/css/theme-toggle.css" rel="stylesheet">
|
||||
<link href="/css/sticky-price.css" rel="stylesheet">
|
||||
<link href="/css/enhanced-animations.css" rel="stylesheet">
|
||||
|
||||
|
||||
</head>
|
||||
<body class="font-sans dark:bg-gray-900 dark:text-gray-100">
|
||||
<!-- Navigation -->
|
||||
<%- include('partials/navigation') %>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
<%- body %>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<%- include('partials/footer') %>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<!-- PWA Service Worker -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then(registration => {
|
||||
console.log('SW registered: ', registration);
|
||||
})
|
||||
.catch(registrationError => {
|
||||
console.log('SW registration failed: ', registrationError);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Analytics -->
|
||||
<% if (settings && settings.seo && settings.seo.googleAnalytics) { %>
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= settings.seo.googleAnalytics %>"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '<%= settings.seo.googleAnalytics %>');
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
<!-- Page-specific scripts -->
|
||||
<%- script %>
|
||||
</body>
|
||||
</html>
|
||||
298
.history/views/services_20251026180633.ejs
Normal file
298
.history/views/services_20251026180633.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-8">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center">
|
||||
<div class="p-8 text-right w-full">
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-20 text-white px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Featured Badge -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="absolute top-4 right-4">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026180657.ejs
Normal file
298
.history/views/services_20251026180657.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-8">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center">
|
||||
<div class="p-8 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181004.ejs
Normal file
298
.history/views/services_20251026181004.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-8">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center">
|
||||
<div class="p-8 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181126.ejs
Normal file
298
.history/views/services_20251026181126.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center p-2.5">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center">
|
||||
<div class="p-8 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181142.ejs
Normal file
298
.history/views/services_20251026181142.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center p-2.5">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center p-2.5">
|
||||
<div class="p-6 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181153.ejs
Normal file
298
.history/views/services_20251026181153.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="max-w-4xl mx-auto space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center p-2.5">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center p-2.5">
|
||||
<div class="p-6 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181439.ejs
Normal file
298
.history/views/services_20251026181439.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center p-2.5">
|
||||
<div class="p-6 text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181456.ejs
Normal file
298
.history/views/services_20251026181456.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center px-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181521.ejs
Normal file
298
.history/views/services_20251026181521.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-1/2 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center px-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181619.ejs
Normal file
298
.history/views/services_20251026181619.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full flex items-center px-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181632.ejs
Normal file
298
.history/views/services_20251026181632.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-left w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026181647.ejs
Normal file
298
.history/views/services_20251026181647.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-left w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-start">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182635.ejs
Normal file
298
.history/views/services_20251026182635.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-left w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-start">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182736.ejs
Normal file
298
.history/views/services_20251026182736.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-start">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182747.ejs
Normal file
298
.history/views/services_20251026182747.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182823.ejs
Normal file
298
.history/views/services_20251026182823.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182903.ejs
Normal file
298
.history/views/services_20251026182903.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-18 py-16">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-6 pr-12 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182917.ejs
Normal file
298
.history/views/services_20251026182917.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-18 py-16">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-18 pr-24 py-16">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026182938.ejs
Normal file
298
.history/views/services_20251026182938.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-18 py-16">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pl-18 pr-24 py-16">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026183037.ejs
Normal file
298
.history/views/services_20251026183037.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-18 py-16">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center py-16" style="padding-left: 72px; padding-right: 96px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026183047.ejs
Normal file
298
.history/views/services_20251026183047.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center py-16" style="padding-left: 72px; padding-right: 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center py-16" style="padding-left: 72px; padding-right: 96px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026183056.ejs
Normal file
298
.history/views/services_20251026183056.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center py-16" style="padding-left: 72px; padding-right: 96px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026183111.ejs
Normal file
298
.history/views/services_20251026183111.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 96px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026183222.ejs
Normal file
298
.history/views/services_20251026183222.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 96px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026184134.ejs
Normal file
298
.history/views/services_20251026184134.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026184156.ejs
Normal file
298
.history/views/services_20251026184156.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026201212.ejs
Normal file
298
.history/views/services_20251026201212.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-3xl text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026201219.ejs
Normal file
298
.history/views/services_20251026201219.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-3xl text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026201350.ejs
Normal file
298
.history/views/services_20251026201350.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026201455.ejs
Normal file
298
.history/views/services_20251026201455.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center" style="padding: 64px 72px;">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center" style="padding: 64px 150px 64px 72px;">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
298
.history/views/services_20251026201614.ejs
Normal file
298
.history/views/services_20251026201614.ejs
Normal file
@@ -0,0 +1,298 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient - using grid layout -->
|
||||
<div class="grid grid-cols-12 h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area - Column 1 (4 columns) -->
|
||||
<div class="col-span-4 h-full flex items-center justify-center px-8 py-8">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area - Column 2 (6 columns) -->
|
||||
<div class="col-span-6 h-full flex items-center px-8 py-8">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
301
.history/views/services_20251026201638.ejs
Normal file
301
.history/views/services_20251026201638.ejs
Normal file
@@ -0,0 +1,301 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient - using grid layout -->
|
||||
<div class="grid grid-cols-12 h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area - Column 1 (4 columns) -->
|
||||
<div class="col-span-4 h-full flex items-center justify-center px-8 py-8">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area - Column 2 (6 columns) -->
|
||||
<div class="col-span-6 h-full flex items-center px-8 py-8">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Spacing Column - Column 3 (2 columns for padding) -->
|
||||
<div class="col-span-2 h-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
301
.history/views/services_20251026201725.ejs
Normal file
301
.history/views/services_20251026201725.ejs
Normal file
@@ -0,0 +1,301 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient - using grid layout -->
|
||||
<div class="grid grid-cols-12 h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area - Column 1 (4 columns) -->
|
||||
<div class="col-span-4 h-full flex items-center justify-center px-8 py-8">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area - Column 2 (6 columns) -->
|
||||
<div class="col-span-6 h-full flex items-center px-8 py-8">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Spacing Column - Column 3 (2 columns for padding) -->
|
||||
<div class="col-span-2 h-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
308
.history/views/services_20251026201934.ejs
Normal file
308
.history/views/services_20251026201934.ejs
Normal file
@@ -0,0 +1,308 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
|
||||
<!-- Decorative elements -->
|
||||
<div class="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div class="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style="animation-delay: 1s;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Gradient fade to center -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Spacing Column - Column 3 (2 columns for padding) -->
|
||||
<div class="col-span-2 h-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
305
.history/views/services_20251026201952.ejs
Normal file
305
.history/views/services_20251026201952.ejs
Normal file
@@ -0,0 +1,305 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
|
||||
<!-- Decorative elements -->
|
||||
<div class="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div class="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style="animation-delay: 1s;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Gradient fade to center -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
305
.history/views/services_20251026202633.ejs
Normal file
305
.history/views/services_20251026202633.ejs
Normal file
@@ -0,0 +1,305 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
<img src="<%= serviceImage %>" alt="<%= service.name %>" class="w-28 h-28 object-contain" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<i class="<%= service.icon || 'fas fa-cog' %> text-white text-6xl" style="display: none;"></i>
|
||||
</div>
|
||||
|
||||
<!-- Decorative elements -->
|
||||
<div class="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div class="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style="animation-delay: 1s;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Gradient fade to center -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
304
.history/views/services_20251026202903.ejs
Normal file
304
.history/views/services_20251026202903.ejs
Normal file
@@ -0,0 +1,304 @@
|
||||
<!-- Services page content starts here -->
|
||||
<link href="/css/fixes.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Services Hero Section - Компактный -->
|
||||
<section class="hero-section-compact bg-gradient-to-br from-blue-600 via-purple-600 to-blue-800">
|
||||
<div class="container mx-auto px-4 py-16 text-center text-white">
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4" data-aos="fade-up">
|
||||
<%- __('services.hero.title') %> <span class="text-yellow-300"><%- __('services.hero.title_highlight') %></span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.hero.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Grid -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="space-y-12">
|
||||
<% if (services && services.length > 0) { %>
|
||||
<% services.forEach((service, index) => { %>
|
||||
<div class="relative overflow-hidden rounded-3xl shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:-translate-y-1"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay="<%= index * 150 %>">
|
||||
|
||||
<!-- Background with Gradient -->
|
||||
<div class="relative h-64 bg-gradient-to-r
|
||||
<% if (index % 4 === 0) { %>from-blue-600 to-purple-600<% } %>
|
||||
<% if (index % 4 === 1) { %>from-green-500 to-teal-600<% } %>
|
||||
<% if (index % 4 === 2) { %>from-purple-600 to-pink-600<% } %>
|
||||
<% if (index % 4 === 3) { %>from-orange-500 to-red-600<% } %>
|
||||
overflow-hidden">
|
||||
|
||||
<!-- Service Image/Icon Area -->
|
||||
<div class="absolute left-0 top-0 w-2/5 h-full flex items-center justify-center px-6 py-4">
|
||||
<div class="relative z-10">
|
||||
<!-- Service illustration -->
|
||||
<div class="w-40 h-40 bg-white bg-opacity-20 rounded-2xl flex items-center justify-center mb-6 backdrop-blur-sm overflow-hidden">
|
||||
<%
|
||||
let serviceImage = '';
|
||||
if (service.category === 'development' || service.name.includes('웹') || service.name.includes('개발')) {
|
||||
serviceImage = '/images/services/web-development.svg';
|
||||
} else if (service.category === 'mobile' || service.name.includes('모바일') || service.name.includes('앱')) {
|
||||
serviceImage = '/images/services/mobile-app.svg';
|
||||
} else if (service.category === 'design' || service.name.includes('디자인') || service.name.includes('UI')) {
|
||||
serviceImage = '/images/services/ui-ux-design.svg';
|
||||
} else if (service.category === 'marketing' || service.name.includes('마케팅')) {
|
||||
serviceImage = '/images/services/digital-marketing.svg';
|
||||
} else if (service.name.includes('브랜딩')) {
|
||||
serviceImage = '/images/services/branding.svg';
|
||||
} else if (service.name.includes('컨설팅')) {
|
||||
serviceImage = '/images/services/consulting.svg';
|
||||
} else {
|
||||
serviceImage = '/images/services/default.svg';
|
||||
}
|
||||
%>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Decorative elements -->
|
||||
<div class="absolute -top-8 -left-8 w-24 h-24 bg-white bg-opacity-10 rounded-full animate-pulse"></div>
|
||||
<div class="absolute -bottom-4 -right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full animate-pulse" style="animation-delay: 1s;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Gradient fade to center -->
|
||||
<div class="absolute right-0 top-0 w-1/2 h-full bg-gradient-to-r from-transparent to-current opacity-30"></div>
|
||||
</div>
|
||||
|
||||
<!-- Service Content Area -->
|
||||
<div class="absolute right-0 top-0 w-3/5 h-full flex items-center pr-16 pl-6 py-4">
|
||||
<div class="text-right w-full">
|
||||
|
||||
<!-- Featured Badge - moved above category -->
|
||||
<% if (service.featured) { %>
|
||||
<div class="mb-3">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<i class="fas fa-star"></i> <%- __('services.cards.popular') %>
|
||||
</span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Service Category Badge -->
|
||||
<div class="inline-block mb-4">
|
||||
<span class="bg-white bg-opacity-90 text-gray-800 px-4 py-2 rounded-full text-sm font-medium backdrop-blur-sm shadow-sm">
|
||||
<%= service.category %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Service Title -->
|
||||
<h3 class="text-3xl font-bold text-white mb-4 leading-tight">
|
||||
<%= service.name %>
|
||||
</h3>
|
||||
|
||||
<!-- Service Description -->
|
||||
<p class="text-white text-opacity-90 mb-6 leading-relaxed text-lg">
|
||||
<%= service.shortDescription || service.description %>
|
||||
</p>
|
||||
|
||||
<!-- Pricing -->
|
||||
<% if (service.pricing) { %>
|
||||
<div class="mb-6">
|
||||
<div class="text-white text-opacity-75 text-sm mb-1"><%- __('services.cards.starting_price') %></div>
|
||||
<div class="text-3xl font-bold text-white">
|
||||
<%= service.pricing.basePrice ? service.pricing.basePrice.toLocaleString() : __('services.cards.consultation') %>
|
||||
<% if (service.pricing.basePrice) { %>
|
||||
<span class="text-lg text-white text-opacity-75">원~</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col gap-3 items-end">
|
||||
<a href="/contact?service=<%= service._id %>"
|
||||
class="bg-white text-gray-900 px-6 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105 shadow-lg">
|
||||
<%- __('services.cards.contact') %>
|
||||
</a>
|
||||
<a href="/calculator?service=<%= service._id %>"
|
||||
class="border-2 border-white text-white px-6 py-3 rounded-xl font-semibold hover:bg-white hover:text-gray-900 transition-all duration-300 transform hover:scale-105">
|
||||
<%- __('services.cards.calculate_cost') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-cogs text-6xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-500 mb-2"><%- __('services.cards.coming_soon') %></h3>
|
||||
<p class="text-gray-400"><%- __('services.cards.coming_soon_desc') %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Section -->
|
||||
<section class="section-padding bg-gray-50">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="text-center mb-16" data-aos="fade-up">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
<%- __('services.process.title') %>
|
||||
</h2>
|
||||
<p class="text-lg text-gray-700 text-center mb-12 max-w-3xl mx-auto">
|
||||
<%- __('services.process.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<!-- Step 1 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="100">
|
||||
<div class="w-20 h-20 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">1</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step1.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step1.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="200">
|
||||
<div class="w-20 h-20 bg-purple-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">2</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step2.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step2.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="300">
|
||||
<div class="w-20 h-20 bg-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">3</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step3.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step3.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="text-center" data-aos="fade-up" data-aos-delay="400">
|
||||
<div class="w-20 h-20 bg-orange-600 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<span class="text-white text-2xl font-bold">4</span>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-4"><%- __('services.process.step4.title') %></h3>
|
||||
<p class="text-gray-700 text-center">
|
||||
<%- __('services.process.step4.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="section-padding">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div data-aos="fade-right">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
|
||||
<%- __('services.why_choose.title') %>
|
||||
</h2>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-rocket text-blue-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.modern_tech.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.modern_tech.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-users text-green-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.expert_team.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.expert_team.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-clock text-purple-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.fast_response.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.fast_response.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 bg-orange-100 rounded-full flex items-center justify-center mr-4 flex-shrink-0">
|
||||
<i class="fas fa-headset text-orange-600 text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2"><%- __('services.why_choose.continuous_support.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.continuous_support.description') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image/Visual -->
|
||||
<div class="relative" data-aos="fade-left">
|
||||
<div class="bg-gradient-to-br from-blue-100 to-purple-100 rounded-2xl p-8 h-96 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<i class="fas fa-award text-6xl text-blue-600 mb-4"></i>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-2"><%- __('services.why_choose.quality_guarantee.title') %></h3>
|
||||
<p class="text-gray-600">
|
||||
<%- __('services.why_choose.quality_guarantee.subtitle') %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="section-padding bg-gradient-to-r from-blue-600 to-purple-600 text-white">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl md:text-4xl font-bold mb-6" data-aos="fade-up">
|
||||
<%- __('services.cta.title') %>
|
||||
</h2>
|
||||
<p class="text-xl mb-8 opacity-90" data-aos="fade-up" data-aos-delay="200">
|
||||
<%- __('services.cta.subtitle') %>
|
||||
</p>
|
||||
|
||||
<a href="/calculator" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.calculate_cost') %>
|
||||
</a>
|
||||
<a href="/portfolio" class="border-2 border-white text-white px-8 py-3 rounded-full hover:bg-white hover:text-blue-600 transition-colors font-semibold">
|
||||
<%- __('services.cta.view_portfolio') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services page content ends here -->
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user