Refactor: Modularize pages into reusable components and update favicon

This commit is contained in:
choibk 2026-01-20 12:43:24 +09:00
parent 5261735536
commit 1ca741eeae
14 changed files with 293 additions and 260 deletions

View File

@ -3,9 +3,9 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" href="/src/assets/logo.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SmartBiz Tech - 소상공인 스마트 기술 파트너</title>
<title>SOKUREE</title>
</head>
<body>

BIN
src/assets/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

View File

@ -1,23 +1,26 @@
const About = () => {
return (
<section id="about" className="section-padding bg-light">
<div className="container">
<h2 className="section-title">회사 소개</h2>
<div className="about-content">
<div className="about-text">
<h3>소상공인과 함께 성장하는 스마트 파트너</h3>
<p>
SmartBiz Tech는 급변하는 디지털 시대에 소상공인 여러분이 경쟁력을 갖출 있도록
최고의 스마트 기술을 합리적인 가격에 공급합니다.
</p>
<p>
단순한 기기 판매가 아닌, 매장 환경 분석부터 설치, 유지보수까지
원스톱 서비스를 제공하여 사장님은 경영에만 집중하실 있도록 돕겠습니다.
</p>
</div>
<>
<section className="about-hero">
<div className="about-intro">
<p>
Sokuree Consultant는 현장의 목소리(데이터)에서 필요한 정보를 <br className="hidden md:block" />
시스템(System) 하여 기업의 지속 가능한 성장을 지원합니다.
</p>
</div>
</div>
</section>
</section>
<section className="vision-mission-grid">
<div className="vision-card">
<h3>Vision</h3>
<p>누구나 쉽게 스마트 경영을 실현하는 세상</p>
</div>
<div className="vision-card">
<h3>Mission</h3>
<p>복잡한 기술을 현장에 맞게 단순화하고, 실질적인 성과를 창출하는 </p>
</div>
</section>
</>
);
};

View File

@ -0,0 +1,43 @@
import React from 'react';
const CaseItem = ({ study }) => {
return (
<div className="case-card">
{/* Image Section */}
{study.image ? (
<div className="case-image-wrapper">
<img
src={study.image}
alt={study.title}
className="case-image"
/>
<div className="case-category-badge">
{study.category.split('/')[0]}
</div>
</div>
) : (
<div className="case-bar"></div>
)}
{/* Content Section */}
<div className="case-content">
{!study.image && (
<div className="case-category-text">
{study.category}
</div>
)}
<h3 className="case-card-title">{study.title}</h3>
<div>
<span className="case-result-badge">
성과: {study.result}
</span>
</div>
<p className="case-details">
{study.details}
</p>
</div>
</div>
);
};
export default CaseItem;

View File

@ -0,0 +1,30 @@
import { Link } from 'react-router-dom';
const CasesPreview = () => {
return (
<section className="section-padding">
<div className="container">
<h2 className="section-title">성공 사례</h2>
<div className="solutions-grid">
<div className="solution-card">
<h3>H사 스마트공장 구축</h3>
<p>생산성 30% 향상, 불량률 50% 감소</p>
</div>
<div className="solution-card">
<h3>D사 ISO 인증 획득</h3>
<p>내부 심사원 양성 프로세스 정립</p>
</div>
<div className="solution-card">
<h3>K사 그룹웨어 도입</h3>
<p>재고 관리 자동화 업무 효율화</p>
</div>
</div>
<div style={{ textAlign: 'center', marginTop: '40px' }}>
<Link to="/cases" className="btn btn-primary">사례 보기</Link>
</div>
</div>
</section>
);
};
export default CasesPreview;

View File

@ -0,0 +1,31 @@
import { Link } from 'react-router-dom';
import { usePosts } from '../hooks/usePosts';
import PostCard from './PostCard';
const LatestNews = () => {
const { posts, loading, error } = usePosts(1, 3); // Fetch 3 latest posts
if (loading) return null;
if (error) return null;
if (posts.length === 0) return null;
return (
<section className="section-padding bg-light">
<div className="container">
<div className="flex justify-between items-end mb-8">
<h2 className="section-title mb-0">최신 소식</h2>
<Link to="/news" className="text-primary font-semibold hover:underline">
전체 보기
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{posts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</div>
</div>
</section>
);
};
export default LatestNews;

View File

@ -0,0 +1,19 @@
const Process = () => {
return (
<section className="section-padding bg-light">
<div className="container">
<h2 className="section-title">진행 프로세스</h2>
<div className="process-grid">
{['진단', '설계', '실행', '정착', '고도화'].map((step, index) => (
<div key={index} className="process-step-card">
<div className="process-step-number">{index + 1}</div>
<h3>{step}</h3>
</div>
))}
</div>
</div>
</section>
);
};
export default Process;

View File

@ -0,0 +1,69 @@
import React from 'react';
const ServiceCurriculum = ({ onDownloadGuide }) => {
return (
<div className="service-section">
<h2 className="section-label">
Sokuree Consultant<br />교육과정
</h2>
<p className="section-desc">현장 전문가로 성장할 있는 다양한 교육 과정을 경험해보세요.</p>
<div className="curriculum-grid">
{/* Col 1 */}
<div className="curriculum-card">
<span className="curriculum-number">01</span>
<h3 className="curriculum-title">경영시스템<br />요구사항 해설</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> ISO 9001 (품질)</li>
<li><span className="curriculum-bullet"></span> ISO 14001 (환경)</li>
<li><span className="curriculum-bullet"></span> ISO 45001 (안전보건)</li>
<li><span className="curriculum-bullet"></span> 시스템 문서화 실무</li>
</ul>
</div>
{/* Col 2 */}
<div className="curriculum-card">
<span className="curriculum-number">02</span>
<h3 className="curriculum-title">내부심사원<br />양성 과정</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> 심사 기법 절차</li>
<li><span className="curriculum-bullet"></span> 체크리스트 작성</li>
<li><span className="curriculum-bullet"></span> 부적합 보고서 작성</li>
<li><span className="curriculum-bullet"></span> Role-Play 실습</li>
</ul>
</div>
{/* Col 3 */}
<div className="curriculum-card">
<span className="curriculum-number">03</span>
<h3 className="curriculum-title">IATF 16949<br />Core Tools</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> APQP / PPAP</li>
<li><span className="curriculum-bullet"></span> FMEA (고장모드)</li>
<li><span className="curriculum-bullet"></span> SPC (통계적공정)</li>
<li><span className="curriculum-bullet"></span> MSA (측정분석)</li>
</ul>
</div>
{/* Col 4 */}
<div className="curriculum-card" style={{ justifyContent: 'space-between' }}>
<div>
<span className="curriculum-number">04</span>
<h3 className="curriculum-title">교육문의 <br />신청안내</h3>
<ul className="curriculum-list">
<li> 32 과정 운영 </li>
<li>맞춤형 출장 교육 가능</li>
</ul>
</div>
<button className="curriculum-btn" onClick={onDownloadGuide}>
<span style={{ fontSize: '1.2rem' }}>📥</span> 교육안내서 보기
</button>
</div>
</div>
</div>
);
};
export default ServiceCurriculum;

View File

@ -0,0 +1,35 @@
import React from 'react';
const ServicePurpose = () => {
return (
<div className="service-section">
<h2 className="section-label">교육 목적</h2>
<p className="section-desc">현장 중심의 실무형 인재 양성을 목표로 하고 있어요.</p>
<div className="purpose-grid">
{/* Purpose Card 1 */}
<div className="purpose-card">
<h3 className="purpose-card-title">스마트 제조 혁신 지원</h3>
<p className="purpose-card-text">중소기업의 스마트한<br />제조 환경 구축을 돕습니다.</p>
<div className="purpose-icon">🏭</div>
</div>
{/* Purpose Card 2 */}
<div className="purpose-card">
<h3 className="purpose-card-title">분야별 기술전문가 양성</h3>
<p className="purpose-card-text">전문 기술 역량 강화를 통한<br />핵심 인재 육성</p>
<div className="purpose-icon">👥</div>
</div>
{/* Purpose Card 3 */}
<div className="purpose-card">
<h3 className="purpose-card-title">현장 중심 실무 학습</h3>
<p className="purpose-card-text">이론과 실무를 겸비한<br />맞춤형 커리큘럼</p>
<div className="purpose-icon">📘</div>
</div>
</div>
</div>
);
};
export default ServicePurpose;

28
src/components/WhyUs.jsx Normal file
View File

@ -0,0 +1,28 @@
const WhyUs = () => {
return (
<section className="section-padding">
<div className="container">
<h2 className="section-title">Why Sokuree?</h2>
<div className="solutions-grid" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
<div className="solution-card">
<div className="solution-icon">🏆</div>
<h3>전문성</h3>
<p>품질/ISO 기반의 검증된 컨설팅</p>
</div>
<div className="solution-card">
<div className="solution-icon">🏭</div>
<h3>현장 중심</h3>
<p>제조 현장에 최적화된 맞춤형 솔루션</p>
</div>
<div className="solution-card">
<div className="solution-icon">🚀</div>
<h3>실행력</h3>
<p>데이터 시스템의 실질적 구현과 안착</p>
</div>
</div>
</div>
</section>
);
};
export default WhyUs;

View File

@ -1,29 +1,11 @@
import consultantProfile from '../assets/consultant_profile.webp';
import AboutIntro from '../components/About';
const About = () => {
return (
<div className="container" style={{ marginTop: '70px', minHeight: '80vh' }}>
{/* Intro Section with Background */}
<section className="about-hero">
<h1 className="section-title" style={{ marginBottom: '30px' }}>회사 소개</h1>
<div className="about-intro">
<p>
Sokuree Consultant는 현장의 목소리(데이터)에서 필요한 정보를 <br className="hidden md:block" />
시스템(System) 하여 기업의 지속 가능한 성장을 지원합니다.
</p>
</div>
</section>
<section className="vision-mission-grid">
<div className="vision-card">
<h3>Vision</h3>
<p>누구나 쉽게 스마트 경영을 실현하는 세상</p>
</div>
<div className="vision-card">
<h3>Mission</h3>
<p>복잡한 기술을 현장에 맞게 단순화하고, 실질적인 성과를 창출하는 </p>
</div>
</section>
<AboutIntro />
<section className="expert-profile">
<h2 className="section-title">대표 컨설턴트</h2>

View File

@ -1,4 +1,5 @@
import React from 'react';
import CaseItem from '../components/CaseItem';
const Cases = () => {
@ -49,41 +50,7 @@ const Cases = () => {
<div className="cases-grid">
{caseStudies.map(study => (
<div key={study.id} className="case-card">
{/* Image Section */}
{study.image ? (
<div className="case-image-wrapper">
<img
src={study.image}
alt={study.title}
className="case-image"
/>
<div className="case-category-badge">
{study.category.split('/')[0]}
</div>
</div>
) : (
<div className="case-bar"></div>
)}
{/* Content Section */}
<div className="case-content">
{!study.image && (
<div className="case-category-text">
{study.category}
</div>
)}
<h3 className="case-card-title">{study.title}</h3>
<div>
<span className="case-result-badge">
성과: {study.result}
</span>
</div>
<p className="case-details">
{study.details}
</p>
</div>
</div>
<CaseItem key={study.id} study={study} />
))}
</div>
</div>

View File

@ -1,112 +1,23 @@
import Hero from '../components/Hero';
import Solutions from '../components/Solutions';
import Contact from '../components/Contact';
import { Link } from 'react-router-dom';
import { usePosts } from '../hooks/usePosts';
import PostCard from '../components/PostCard';
import WhyUs from '../components/WhyUs';
import Process from '../components/Process';
import CasesPreview from '../components/CasesPreview';
import LatestNews from '../components/LatestNews';
const Home = () => {
return (
<>
<Hero />
{/* Why Us Section */}
<section className="section-padding">
<div className="container">
<h2 className="section-title">Why Sokuree?</h2>
<div className="solutions-grid" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
<div className="solution-card">
<div className="solution-icon">🏆</div>
<h3>전문성</h3>
<p>품질/ISO 기반의 검증된 컨설팅</p>
</div>
<div className="solution-card">
<div className="solution-icon">🏭</div>
<h3>현장 중심</h3>
<p>제조 현장에 최적화된 맞춤형 솔루션</p>
</div>
<div className="solution-card">
<div className="solution-icon">🚀</div>
<h3>실행력</h3>
<p>데이터 시스템의 실질적 구현과 안착</p>
</div>
</div>
</div>
</section>
<WhyUs />
<Solutions />
{/* Process Section */}
<section className="section-padding bg-light">
<div className="container">
<h2 className="section-title">진행 프로세스</h2>
<div className="process-grid">
{['진단', '설계', '실행', '정착', '고도화'].map((step, index) => (
<div key={index} className="process-step-card">
<div className="process-step-number">{index + 1}</div>
<h3>{step}</h3>
</div>
))}
</div>
</div>
</section>
{/* Cases Preview */}
<section className="section-padding">
<div className="container">
<h2 className="section-title">성공 사례</h2>
<div className="solutions-grid">
<div className="solution-card">
<h3>H사 스마트공장 구축</h3>
<p>생산성 30% 향상, 불량률 50% 감소</p>
</div>
<div className="solution-card">
<h3>D사 ISO 인증 획득</h3>
<p>내부 심사원 양성 프로세스 정립</p>
</div>
<div className="solution-card">
<h3>K사 그룹웨어 도입</h3>
<p>재고 관리 자동화 업무 효율화</p>
</div>
</div>
<div style={{ textAlign: 'center', marginTop: '40px' }}>
<Link to="/cases" className="btn btn-primary">사례 보기</Link>
</div>
</div>
</section>
{/* Latest News Section */}
<LatestNewsSection />
<Process />
<CasesPreview />
<LatestNews />
<Contact />
</>
);
};
const LatestNewsSection = () => {
const { posts, loading, error } = usePosts(1, 3); // Fetch 3 latest posts
if (loading) return null;
if (error) return null;
if (posts.length === 0) return null;
return (
<section className="section-padding bg-light">
<div className="container">
<div className="flex justify-between items-end mb-8">
<h2 className="section-title mb-0">최신 소식</h2>
<Link to="/news" className="text-primary font-semibold hover:underline">
전체 보기
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{posts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</div>
</div>
</section>
);
}
export default Home;

View File

@ -1,5 +1,7 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import ServicePurpose from '../components/ServicePurpose';
import ServiceCurriculum from '../components/ServiceCurriculum';
const ServiceDetail = () => {
const navigate = useNavigate();
@ -26,97 +28,10 @@ const ServiceDetail = () => {
<div className="service-content-wrapper">
{/* Section 1: Education Purpose (3 Cards) */}
<div className="service-section">
<h2 className="section-label">교육 목적</h2>
<p className="section-desc">현장 중심의 실무형 인재 양성을 목표로 하고 있어요.</p>
<div className="purpose-grid">
{/* Purpose Card 1 */}
<div className="purpose-card">
<h3 className="purpose-card-title">스마트 제조 혁신 지원</h3>
<p className="purpose-card-text">중소기업의 스마트한<br />제조 환경 구축을 돕습니다.</p>
<div className="purpose-icon">🏭</div>
</div>
{/* Purpose Card 2 */}
<div className="purpose-card">
<h3 className="purpose-card-title">분야별 기술전문가 양성</h3>
<p className="purpose-card-text">전문 기술 역량 강화를 통한<br />핵심 인재 육성</p>
<div className="purpose-icon">👥</div>
</div>
{/* Purpose Card 3 */}
<div className="purpose-card">
<h3 className="purpose-card-title">현장 중심 실무 학습</h3>
<p className="purpose-card-text">이론과 실무를 겸비한<br />맞춤형 커리큘럼</p>
<div className="purpose-icon">📘</div>
</div>
</div>
</div>
<ServicePurpose />
{/* Section 2: Curriculum (4 Numbered Columns) */}
<div className="service-section">
<h2 className="section-label">
Sokuree Consultant<br />교육과정
</h2>
<p className="section-desc">현장 전문가로 성장할 있는 다양한 교육 과정을 경험해보세요.</p>
<div className="curriculum-grid">
{/* Col 1 */}
<div className="curriculum-card">
<span className="curriculum-number">01</span>
<h3 className="curriculum-title">경영시스템<br />요구사항 해설</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> ISO 9001 (품질)</li>
<li><span className="curriculum-bullet"></span> ISO 14001 (환경)</li>
<li><span className="curriculum-bullet"></span> ISO 45001 (안전보건)</li>
<li><span className="curriculum-bullet"></span> 시스템 문서화 실무</li>
</ul>
</div>
{/* Col 2 */}
<div className="curriculum-card">
<span className="curriculum-number">02</span>
<h3 className="curriculum-title">내부심사원<br />양성 과정</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> 심사 기법 절차</li>
<li><span className="curriculum-bullet"></span> 체크리스트 작성</li>
<li><span className="curriculum-bullet"></span> 부적합 보고서 작성</li>
<li><span className="curriculum-bullet"></span> Role-Play 실습</li>
</ul>
</div>
{/* Col 3 */}
<div className="curriculum-card">
<span className="curriculum-number">03</span>
<h3 className="curriculum-title">IATF 16949<br />Core Tools</h3>
<ul className="curriculum-list">
<li><span className="curriculum-bullet"></span> APQP / PPAP</li>
<li><span className="curriculum-bullet"></span> FMEA (고장모드)</li>
<li><span className="curriculum-bullet"></span> SPC (통계적공정)</li>
<li><span className="curriculum-bullet"></span> MSA (측정분석)</li>
</ul>
</div>
{/* Col 4 */}
<div className="curriculum-card" style={{ justifyContent: 'space-between' }}>
<div>
<span className="curriculum-number">04</span>
<h3 className="curriculum-title">교육문의 <br />신청안내</h3>
<ul className="curriculum-list">
<li> 32 과정 운영 </li>
<li>맞춤형 출장 교육 가능</li>
</ul>
</div>
<button className="curriculum-btn" onClick={handleDownloadGuide}>
<span style={{ fontSize: '1.2rem' }}>📥</span> 교육안내서 보기
</button>
</div>
</div>
</div>
<ServiceCurriculum onDownloadGuide={handleDownloadGuide} />
{/* Bottom CTA Banner */}
<div className="cta-banner">